开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜