Show More
@@ -119,6 +119,27 b' class _CONSOLE_SCREEN_BUFFER_INFO(ctypes' | |||||
119 |
|
119 | |||
120 | _STD_ERROR_HANDLE = _DWORD(-12).value |
|
120 | _STD_ERROR_HANDLE = _DWORD(-12).value | |
121 |
|
121 | |||
|
122 | # CreateToolhelp32Snapshot, Process32First, Process32Next | |||
|
123 | _TH32CS_SNAPPROCESS = 0x00000002 | |||
|
124 | _MAX_PATH = 260 | |||
|
125 | ||||
|
126 | class _tagPROCESSENTRY32(ctypes.Structure): | |||
|
127 | _fields_ = [('dwsize', _DWORD), | |||
|
128 | ('cntUsage', _DWORD), | |||
|
129 | ('th32ProcessID', _DWORD), | |||
|
130 | ('th32DefaultHeapID', ctypes.c_void_p), | |||
|
131 | ('th32ModuleID', _DWORD), | |||
|
132 | ('cntThreads', _DWORD), | |||
|
133 | ('th32ParentProcessID', _DWORD), | |||
|
134 | ('pcPriClassBase', _LONG), | |||
|
135 | ('dwFlags', _DWORD), | |||
|
136 | ('szExeFile', ctypes.c_char * _MAX_PATH)] | |||
|
137 | ||||
|
138 | def __init__(self): | |||
|
139 | super(_tagPROCESSENTRY32, self).__init__() | |||
|
140 | self.dwsize = ctypes.sizeof(self) | |||
|
141 | ||||
|
142 | ||||
122 | # types of parameters of C functions used (required by pypy) |
|
143 | # types of parameters of C functions used (required by pypy) | |
123 |
|
144 | |||
124 | _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p, |
|
145 | _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p, | |
@@ -186,6 +207,15 b' except AttributeError:' | |||||
186 | _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM] |
|
207 | _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM] | |
187 | _user32.EnumWindows.restype = _BOOL |
|
208 | _user32.EnumWindows.restype = _BOOL | |
188 |
|
209 | |||
|
210 | _kernel32.CreateToolhelp32Snapshot.argtypes = [_DWORD, _DWORD] | |||
|
211 | _kernel32.CreateToolhelp32Snapshot.restype = _BOOL | |||
|
212 | ||||
|
213 | _kernel32.Process32First.argtypes = [_HANDLE, ctypes.c_void_p] | |||
|
214 | _kernel32.Process32First.restype = _BOOL | |||
|
215 | ||||
|
216 | _kernel32.Process32Next.argtypes = [_HANDLE, ctypes.c_void_p] | |||
|
217 | _kernel32.Process32Next.restype = _BOOL | |||
|
218 | ||||
189 | def _raiseoserror(name): |
|
219 | def _raiseoserror(name): | |
190 | err = ctypes.WinError() |
|
220 | err = ctypes.WinError() | |
191 | raise OSError(err.errno, '%s: %s' % (name, err.strerror)) |
|
221 | raise OSError(err.errno, '%s: %s' % (name, err.strerror)) | |
@@ -309,6 +339,51 b' def termwidth():' | |||||
309 | width = csbi.srWindow.Right - csbi.srWindow.Left |
|
339 | width = csbi.srWindow.Right - csbi.srWindow.Left | |
310 | return width |
|
340 | return width | |
311 |
|
341 | |||
|
342 | def _1stchild(pid): | |||
|
343 | '''return the 1st found child of the given pid | |||
|
344 | ||||
|
345 | None is returned when no child is found''' | |||
|
346 | pe = _tagPROCESSENTRY32() | |||
|
347 | ||||
|
348 | # create handle to list all processes | |||
|
349 | ph = _kernel32.CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0) | |||
|
350 | if ph == _INVALID_HANDLE_VALUE: | |||
|
351 | raise ctypes.WinError | |||
|
352 | try: | |||
|
353 | r = _kernel32.Process32First(ph, ctypes.byref(pe)) | |||
|
354 | # loop over all processes | |||
|
355 | while r: | |||
|
356 | if pe.th32ParentProcessID == pid: | |||
|
357 | # return first child found | |||
|
358 | return pe.th32ProcessID | |||
|
359 | r = _kernel32.Process32Next(ph, ctypes.byref(pe)) | |||
|
360 | finally: | |||
|
361 | _kernel32.CloseHandle(ph) | |||
|
362 | if _kernel32.GetLastError() != _ERROR_NO_MORE_FILES: | |||
|
363 | raise ctypes.WinError | |||
|
364 | return None # no child found | |||
|
365 | ||||
|
366 | class _tochildpid(int): # pid is _DWORD, which always matches in an int | |||
|
367 | '''helper for spawndetached, returns the child pid on conversion to string | |||
|
368 | ||||
|
369 | Does not resolve the child pid immediately because the child may not yet be | |||
|
370 | started. | |||
|
371 | ''' | |||
|
372 | def childpid(self): | |||
|
373 | '''returns the child pid of the first found child of the process | |||
|
374 | with this pid''' | |||
|
375 | return _1stchild(self) | |||
|
376 | def __str__(self): | |||
|
377 | # run when the pid is written to the file | |||
|
378 | ppid = self.childpid() | |||
|
379 | if ppid is None: | |||
|
380 | # race, child has exited since check | |||
|
381 | # fall back to this pid. Its process will also have disappeared, | |||
|
382 | # raising the same error type later as when the child pid would | |||
|
383 | # be returned. | |||
|
384 | return " %d" % self | |||
|
385 | return str(ppid) | |||
|
386 | ||||
312 | def spawndetached(args): |
|
387 | def spawndetached(args): | |
313 | # No standard library function really spawns a fully detached |
|
388 | # No standard library function really spawns a fully detached | |
314 | # process under win32 because they allocate pipes or other objects |
|
389 | # process under win32 because they allocate pipes or other objects | |
@@ -339,7 +414,8 b' def spawndetached(args):' | |||||
339 | if not res: |
|
414 | if not res: | |
340 | raise ctypes.WinError |
|
415 | raise ctypes.WinError | |
341 |
|
416 | |||
342 | return pi.dwProcessId |
|
417 | # _tochildpid because the process is the child of COMSPEC | |
|
418 | return _tochildpid(pi.dwProcessId) | |||
343 |
|
419 | |||
344 | def unlink(f): |
|
420 | def unlink(f): | |
345 | '''try to implement POSIX' unlink semantics on Windows''' |
|
421 | '''try to implement POSIX' unlink semantics on Windows''' |
General Comments 0
You need to be logged in to leave comments.
Login now