Package Ganga :: Package Utility :: Package AMGAServerTools :: Module winprocess
[hide private]
[frames] | no frames]

Source Code for Module Ganga.Utility.AMGAServerTools.winprocess

  1  """ 
  2  Windows Process Control 
  3   
  4  winprocess.run launches a child process and returns the exit code. 
  5  Optionally, it can: 
  6    redirect stdin, stdout & stderr to files 
  7    run the command as another user 
  8    limit the process's running time 
  9    control the process window (location, size, window state, desktop) 
 10  Works on Windows NT, 2000 & XP. Requires Mark Hammond's win32 
 11  extensions. 
 12   
 13  This code is free for any purpose, with no warranty of any kind. 
 14  -- John B. Dell'Aquila <jbd@alum.mit.edu> 
 15  """ 
 16   
 17  import win32api, win32process, win32security 
 18  import win32event, win32con, msvcrt, win32gui 
 19   
 20   
21 -def logonUser(loginString):
22 """ 23 Login as specified user and return handle. 24 loginString: 'Domain\nUser\nPassword'; for local 25 login use . or empty string as domain 26 e.g. '.\nadministrator\nsecret_password' 27 """ 28 domain, user, passwd = loginString.split('\n') 29 return win32security.LogonUser( 30 user, 31 domain, 32 passwd, 33 win32con.LOGON32_LOGON_INTERACTIVE, 34 win32con.LOGON32_PROVIDER_DEFAULT 35 )
36 37
38 -class Process:
39 """ 40 A Windows process. 41 """ 42
43 - def __init__(self, cmd, login=None, 44 hStdin=None, hStdout=None, hStderr=None, 45 show=1, xy=None, xySize=None, 46 desktop=None):
47 """ 48 Create a Windows process. 49 cmd: command to run 50 login: run as user 'Domain\nUser\nPassword' 51 hStdin, hStdout, hStderr: 52 handles for process I/O; default is caller's stdin, 53 stdout & stderr 54 show: wShowWindow (0=SW_HIDE, 1=SW_NORMAL, ...) 55 xy: window offset (x, y) of upper left corner in pixels 56 xySize: window size (width, height) in pixels 57 desktop: lpDesktop - name of desktop e.g. 'winsta0\\default' 58 None = inherit current desktop 59 '' = create new desktop if necessary 60 61 User calling login requires additional privileges: 62 Act as part of the operating system [not needed on Windows XP] 63 Increase quotas 64 Replace a process level token 65 Login string must EITHER be an administrator's account 66 (ordinary user can't access current desktop - see Microsoft 67 Q165194) OR use desktop='' to run another desktop invisibly 68 (may be very slow to startup & finalize). 69 """ 70 si = win32process.STARTUPINFO() 71 si.dwFlags = (win32con.STARTF_USESTDHANDLES ^ 72 win32con.STARTF_USESHOWWINDOW) 73 if hStdin is None: 74 si.hStdInput = win32api.GetStdHandle(win32api.STD_INPUT_HANDLE) 75 else: 76 si.hStdInput = hStdin 77 if hStdout is None: 78 si.hStdOutput = win32api.GetStdHandle(win32api.STD_OUTPUT_HANDLE) 79 else: 80 si.hStdOutput = hStdout 81 if hStderr is None: 82 si.hStdError = win32api.GetStdHandle(win32api.STD_ERROR_HANDLE) 83 else: 84 si.hStdError = hStderr 85 si.wShowWindow = show 86 if xy is not None: 87 si.dwX, si.dwY = xy 88 si.dwFlags ^= win32con.STARTF_USEPOSITION 89 if xySize is not None: 90 si.dwXSize, si.dwYSize = xySize 91 si.dwFlags ^= win32con.STARTF_USESIZE 92 if desktop is not None: 93 si.lpDesktop = desktop 94 procArgs = (None, # appName 95 cmd, # commandLine 96 None, # processAttributes 97 None, # threadAttributes 98 1, # bInheritHandles 99 win32process.CREATE_NEW_CONSOLE, # dwCreationFlags 100 None, # newEnvironment 101 None, # currentDirectory 102 si) # startupinfo 103 if login is not None: 104 hUser = logonUser(login) 105 win32security.ImpersonateLoggedOnUser(hUser) 106 procHandles = win32process.CreateProcessAsUser(hUser, *procArgs) 107 win32security.RevertToSelf() 108 else: 109 procHandles = win32process.CreateProcess(*procArgs) 110 self.hProcess, self.hThread, self.PId, self.TId = procHandles
111
112 - def wait(self, mSec=None):
113 """ 114 Wait for process to finish or for specified number of 115 milliseconds to elapse. 116 """ 117 if mSec is None: 118 mSec = win32event.INFINITE 119 return win32event.WaitForSingleObject(self.hProcess, mSec)
120
121 - def kill(self, gracePeriod=5000):
122 """ 123 Kill process. Try for an orderly shutdown via WM_CLOSE. If 124 still running after gracePeriod (5 sec. default), terminate. 125 """ 126 win32gui.EnumWindows(self.__close__, 0) 127 if self.wait(gracePeriod) != win32event.WAIT_OBJECT_0: 128 win32process.TerminateProcess(self.hProcess, 0) 129 win32api.Sleep(100) # wait for resources to be released
130
131 - def __close__(self, hwnd, dummy):
132 """ 133 EnumWindows callback - sends WM_CLOSE to any window 134 owned by this process. 135 """ 136 TId, PId = win32process.GetWindowThreadProcessId(hwnd) 137 if PId == self.PId: 138 win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)
139
140 - def exitCode(self):
141 """ 142 Return process exit code. 143 """ 144 return win32process.GetExitCodeProcess(self.hProcess)
145 146
147 -def run(cmd, mSec=None, stdin=None, stdout=None, stderr=None, **kw):
148 """ 149 Run cmd as a child process and return exit code. 150 mSec: terminate cmd after specified number of milliseconds 151 stdin, stdout, stderr: 152 file objects for child I/O (use hStdin etc. to attach 153 handles instead of files); default is caller's stdin, 154 stdout & stderr; 155 kw: see Process.__init__ for more keyword options 156 """ 157 if stdin is not None: 158 kw['hStdin'] = msvcrt.get_osfhandle(stdin.fileno()) 159 if stdout is not None: 160 kw['hStdout'] = msvcrt.get_osfhandle(stdout.fileno()) 161 if stderr is not None: 162 kw['hStderr'] = msvcrt.get_osfhandle(stderr.fileno()) 163 child = Process(cmd, **kw) 164 if child.wait(mSec) != win32event.WAIT_OBJECT_0: 165 child.kill() 166 raise WindowsError, 'process timeout exceeded' 167 return child.exitCode()
168 169 170 if __name__ == '__main__': 171 172 # Pipe commands to a shell and display the output in notepad 173 print 'Testing winprocess.py...' 174 175 import tempfile 176 177 timeoutSeconds = 15 178 cmdString = """\ 179 REM Test of winprocess.py piping commands to a shell.\r 180 REM This window will close in %d seconds.\r 181 vol\r 182 net user\r 183 _this_is_a_test_of_stderr_\r 184 """ % timeoutSeconds 185 186 cmd, out = tempfile.TemporaryFile(), tempfile.TemporaryFile() 187 cmd.write(cmdString) 188 cmd.seek(0) 189 190 print 'CMD.EXE exit code:', run('cmd.exe', show=0, stdin=cmd, 191 stdout=out, stderr=out) 192 cmd.close() 193 print 'NOTEPAD exit code:', run('notepad.exe %s' % out.file.name, 194 show=win32con.SW_MAXIMIZE, 195 mSec=timeoutSeconds*1000) 196 out.close() 197