Hi,
I spent some time finding a safe way to kill/terminate a process on
Windows. Attached is my current version, modelled after a DDJ article.
It should work for gui and console applications, has lots of unnecessary
print output, uses ctypes for a call to CreateRemoteThread, and bypasses
(I think ?) any signal handlers that might be registered.
I hope this is useful for someone.
Two questions:
- The first is the request to include CreateRemoteThread in win32api
(which I will post on sourceforge)
- Does anyone know a similarly safe way for terminating a process so
that a SIGINT/SIGTERM handler will still be called (without the need for
a shared console or process group ids)?
cheers,
stefan
'''win32helper - for now only SafeTerminateProcess, modelled after the DDJ
article:
http://www.ddj.com/showArticle.jhtml?documentID=wdj9907c&pgno=9
( A Safer Alternative to TerminateProcess() )
"Safely terminate a process by creating a remote thread in the process that
calls ExitProcess"
'''
import win32api
import win32con
import win32process
import win32event
import win32com.client
import ctypes
def getChildrenPidsOfPid(pid):
print 'getting children of %s' % pid
wmi = win32com.client.GetObject('winmgmts:')
children = wmi.ExecQuery('Select * from win32_process where
ParentProcessId=%s' % pid)
pids = []
for proc in children:
print 'child: %s %s' % (proc.Name, proc.Properties_('ProcessId'))
pids.append(proc.Properties_('ProcessId'))
return pids
def SafeTerminateProcess(pid):
'''BOOL SafeTerminateProcess(pid), originally: (HANDLE hProcess, UINT
uExitCode),
returns non-zero value on success.
'''
success = False
for child in getChildrenPidsOfPid(pid):
SafeTerminateProcess(child)
### this is only for testing, sometimes terminating the children causes
parental suicide
import time; time.sleep(5)
print 'trying to terminate pid %s' % pid
handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid)
exitcode = win32process.GetExitCodeProcess(handle)
if exitcode == win32con.STILL_ACTIVE:
print 'need to terminate pid %s' % pid
hKernel = win32api.GetModuleHandle("Kernel32")
procExit = win32api.GetProcAddress(hKernel, "ExitProcess")
# the following is not (yet?) in win32process:
hRemoteT = ctypes.windll.kernel32.CreateRemoteThread(handle.handle,
None, 0, procExit,
ctypes.c_void_p(-1), 0, None)
if not hRemoteT:
print 'bad, no thread'
else:
print 'waiting after starting remote thread'
retval = win32event.WaitForSingleObject(handle, 5000) # wait 5
seconds
if retval == win32con.WAIT_TIMEOUT:
print 'argh, timeout elapsed'
win32api.CloseHandle(hRemoteT)
success = True
else:
success = True
print 'pid %s already dead' % pid
win32api.CloseHandle(handle)
print 'success is %s for pid %s' % (success, pid)
return success
_______________________________________________
Python-win32 mailing list
Python-win32@python.org
http://mail.python.org/mailman/listinfo/python-win32