Search code examples
pythonpywin32

get window handler from started process


I see there's win32process.GetWindowThreadProcess() that gets a window handler and returns it's process id. Is there a way to do the opposite: get the window handler of a running process by it's process id? Something like win32gui.GetWindowHandler(processId) ?

Specifically What I'm trying to do:

I have a python script that runs an external program, lets say notepad.exe.
Notepad is fired when runProgram() method is called. I want to prevent this method from running Notepad more than once. I accomplish this in the following way, using win32process:

import win32process as process
import sys

PORTABLE_APPLICATION_LOCATION = "C:\\Windows\\system32\\notepad.exe"
processHandler = -1

def runProgram():
    global processHandler
    #don't run a process more than once
    if (isLiveProcess(processHandler)):
        #Bring focus back to running window!
        return;
    try:
        startObj = process.STARTUPINFO()
        myProcessTuple = process.CreateProcess(PORTABLE_APPLICATION_LOCATION,None,None,None,8,8,None,None,startObj)
        processHandler = myProcessTuple[2]
    except:
        print(sys.exc_info[0])

def isLiveProcess(processHandler): #Process handler is dwProcessId
    processList = process.EnumProcesses()
    for aProcess in processList:
        if (aProcess == processHandler):
            return True
    return False

runProgram()

This works as expected, but if the process is found to be already alive, I'd like to bring it's window back to front with win32gui


Solution

  • I dont think that Windows API provides a method for this , but you could iterate over all open windows , and find the one that belongs to you .

    I have modified your program so it looks like this :

    import win32process
    import win32process as process
    import win32gui
    import sys
    
    PORTABLE_APPLICATION_LOCATION = "C:\\Windows\\system32\\notepad.exe"
    processHandler = -1
    
    
    def callback(hwnd, procid):
        if procid in  win32process.GetWindowThreadProcessId(hwnd):
            win32gui.SetForegroundWindow(hwnd)
    
    def show_window_by_process(procid):
        win32gui.EnumWindows(callback, procid)
    
    
    def runProgram():
        global processHandler
        #don't run a process more than once
        if (isLiveProcess(processHandler)):
            #Bring focus back to running window!
            show_window_by_process(processHandler)
            return;
        try:
            startObj = process.STARTUPINFO()
            myProcessTuple = process.CreateProcess(PORTABLE_APPLICATION_LOCATION,None,None,None,8,8,None,None,startObj)
            processHandler = myProcessTuple[2]
        except:
            print(sys.exc_info[0])
    
    def isLiveProcess(processHandler): #Process handler is dwProcessId
        processList = process.EnumProcesses()
        for aProcess in processList:
            if (aProcess == processHandler):
                return True
        return False
    
     runProgram()