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

Reply via email to