2011-01-14 50 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的文档。