2011-01-14 90 views
1

我想在另一個用戶下執行一個python腳本(通過python進程)。我在網絡上發現了部分代碼,並且工作得很好;除了一件事。ctypes後Python進程失敗CreateProcessWithLogonW執行

當進程終止時,python失敗。

因此要清楚,不同用戶下的第二個python進程與CreateProcessWithLogonW執行得很好,但第一個腳本失敗(我認爲)。

我可能是錯在我的思想,我的代碼使用的可能是錯的...

任何想法可能會導致一個Python進程變得反應遲鈍?

我已經嘗試了很多東西(即像在兩個腳本中放置sys.exit(0)以清楚說明任務已完成...),但無法獲取它。

我Win7上運行與Python 2.6 64位

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() 

感謝任何啓示(:

回答

1

HANDLE是64位系統上的64位整數類型。嘗試「從ctypes.wintypes導入HANDLE」而不是「HANDLE = DWORD」

+0

這就是它,非常感謝! – Xavier 2011-01-14 04:26:46

1

檢查你的論據lpApplicationNamelpCommandLine;修復它是一種方法前者爲NULL,後者爲完整命令行:

p = CreateProcessWithLogonW('user', 
          'domain', 
          'password', 
          0, 
          NULL, 
          r'C:\Python26\python.exe C:\mySimpleScript.py') 

有關詳細信息,請參閱CreateProcessWithLogonW的文檔。