Python process fail after ctypes CreateProcessWithLogonW execution
I'm trying to execute a python script (through a python process) under another user. I found part of this code on the web and works pretty well; except one thing.
When the process terminate, python fails.
So to be clear, the second python process under the different user execute well with CreateProcessWithLogonW, but the first script fails (I think).
I might be wrong in my thinking, and my code usage might be wrong ...
Any idea what could cause one python process to become unresponsive?
I've tried a lot of things (i.e. like placing sys.exit(0) in both script to make it clear that the task is done ...), but cannot get it.
I'm running on win7 with python 2.6 64bit
import ctypes
import win32api
import win32event
import win32process
NULL = 0
TRUE = 1
FALSE = 0
INVALID_HANDLE_VALUE = -1
CREATE_DEFAULT_ERROR_MODE = 0x04000000
DETACHED_PROCESS = 0x00000008
WORD = ctypes.c_ushort
DWORD = ctypes.c_uint
LPSTR = ctypes.c_char_p
LPBYTE = LPSTR
HANDLE = DWORD
# typedef struct _PROCESS_INFORMATION {
# HANDLE hProcess;
# HANDLE hThread;
# DWORD dwProcessId;
# DWORD dwThreadId;
# } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
class PROCESS_INFORMATION(ctypes.Structure):
_pack_ = 1
_fields_ = [
('hProcess', HANDLE),
('hThread', HANDLE),
('dwProcessId', DWORD),
('dwThreadId', DWORD),
]
# typedef struct _STARTUPINFO {
# DWORD cb;
# LPSTR lpReserved;
# LPSTR lpDesktop;
# LPSTR lpTitle;
# DWORD dwX;
# DWORD dwY;
# DWORD dwXSize;
# DWORD dwYSize;
# DWORD dwXCountChars;
# DWORD dwYCountChars;
# DWORD dwFillAttribute;
# DWORD dwFlags;
# WORD wShowWindow;
# WORD cbReserved2;
# LPBYTE lpReserved2;
# HANDLE hStdInput;
# HANDLE hStdOutput;
# HANDLE hStdError;
# } STARTUPINFO, *LPSTARTUPINFO;
class STARTUPINFO(ctypes.Structure):
_pack_ = 1
_fields_ = [
('cb', DWORD),
('lpReserved', DWORD), # LPSTR
('lpDesktop', LPSTR),
('lpTitle', LPSTR),
('dwX', DWORD),
('dwY', DWORD),
('dwXSize', DWORD),
('dwYSize', DWORD),
('dwXCountChars', DWORD),
('dwYCountChars', DWORD),
('dwFillAttribute', DWORD),
('dwFlags', DWORD),
('wShowWindow', WORD),
('cbReserved2', WORD),
('lpReserved2', DWORD), # LPBYTE
('hStdInput', DWORD),
('hStdOutput', DWORD),
('hStdError', DWORD),
]
# BOOL WINAPI CreateProcessWithLogonW(
# __in LPCWSTR lpUsername,
# __in_opt LPCWSTR lpDomain,
# __in LPCWSTR lpPassword,
开发者_开发问答 # __in DWORD dwLogonFlags,
# __in_opt LPCWSTR lpApplicationName,
# __inout_opt LPWSTR lpCommandLine,
# __in DWORD dwCreationFlags,
# __in_opt LPVOID lpEnvironment,
# __in_opt LPCWSTR lpCurrentDirectory,
# __in LPSTARTUPINFOW lpStartupInfo,
# __out LPPROCESS_INFORMATION lpProcessInfo
# );
def CreateProcessWithLogonW(lpUsername=None, lpDomain=None, lpPassword=None,
dwLogonFlags=0, lpApplicationName=None, lpCommandLine=None,
dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None,
lpStartupInfo = None):
if not lpUsername:
lpUsername = NULL
else:
lpUsername = ctypes.c_wchar_p(lpUsername)
if not lpDomain:
lpDomain = NULL
else:
lpDomain = ctypes.c_wchar_p(lpDomain)
if not lpPassword:
lpPassword = NULL
else:
lpPassword = ctypes.c_wchar_p(lpPassword)
if not lpApplicationName:
lpApplicationName = NULL
else:
lpApplicationName = ctypes.c_wchar_p(lpApplicationName)
if not lpCommandLine:
lpCommandLine = NULL
else:
lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine)
if not lpEnvironment:
lpEnvironment = NULL
else:
lpEnvironment = ctypes.c_wchar_p(lpEnvironment)
if not lpCurrentDirectory:
lpCurrentDirectory = NULL
else:
lpCurrentDirectory = ctypes.c_wchar_p(lpCurrentDirectory)
if not lpStartupInfo:
lpStartupInfo = STARTUPINFO()
lpStartupInfo.cb = ctypes.sizeof(STARTUPINFO)
lpStartupInfo.lpReserved = 0
lpStartupInfo.lpDesktop = 0
lpStartupInfo.lpTitle = 0
lpStartupInfo.dwFlags = 0
lpStartupInfo.cbReserved2 = 0
lpStartupInfo.lpReserved2 = 0
lpStartupInfo.hStdInput = win32api.GetStdHandle(win32api.STD_INPUT_HANDLE)
lpStartupInfo.hStdOutput = win32api.GetStdHandle(win32api.STD_OUTPUT_HANDLE)
lpStartupInfo.hStdError = win32api.GetStdHandle(win32api.STD_ERROR_HANDLE)
lpProcessInformation = PROCESS_INFORMATION()
lpProcessInformation.hProcess = INVALID_HANDLE_VALUE
lpProcessInformation.hThread = INVALID_HANDLE_VALUE
lpProcessInformation.dwProcessId = 0
lpProcessInformation.dwThreadId = 0
dwCreationFlags |= win32process.CREATE_NEW_CONSOLE
success = ctypes.windll.advapi32.CreateProcessWithLogonW(lpUsername,
lpDomain,
lpPassword,
dwLogonFlags,
lpApplicationName,
ctypes.byref(lpCommandLine),
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
ctypes.byref(lpStartupInfo),
ctypes.byref(lpProcessInformation))
if success == FALSE:
raise ctypes.WinError()
win32event.WaitForSingleObject(lpProcessInformation.hProcess, win32event.INFINITE)
ctypes.windll.kernel32.CloseHandle(lpProcessInformation.hProcess)
ctypes.windll.kernel32.CloseHandle(lpProcessInformation.hThread)
return lpProcessInformation
def test():
p = CreateProcessWithLogonW('user',
'domain',
'password',
0,
r'C:\Python26\python.exe',
r'C:\Python26\python.exe C:\mySimpleScript.py')
if __name__ == '__main__':
test()
Thanks for any enlightment (:
HANDLE is a 64 bit integer type on 64 bit systems. Try "from ctypes.wintypes import HANDLE" instead of "HANDLE = DWORD"
Check your arguments for lpApplicationName and lpCommandLine; one way to fix it is to pass NULL for the former and the complete command line for the latter:
p = CreateProcessWithLogonW('user',
'domain',
'password',
0,
NULL,
r'C:\Python26\python.exe C:\mySimpleScript.py')
See the docs for CreateProcessWithLogonW for details.
精彩评论