Find the window for my subprocess

Introduction

The challenge: to find the windows belonging to the process you've just kicked off.

The idea is that if, for example, you run a notepad session, you then want to read the text entered into it, or close it down if it's been open too long, or whatever. The problem is that Windows doesn't provide a straightforward mapping from process id to window. The situation is complicated because some process may not have a window, or may have several. The approach below uses the venerable technique of iterating over all top-level windows and finding the ones belonging to a process id. It only considers windows which are visible and enabled (which is generally what you want) and returns a list of the ones associated with your pid.

The test code runs up a notepad session using subprocess and passes its pid along after a couple of seconds, since experience showed that firing off the search too soon wouldn't find the window. Obviously, your own code could do whatever you wanted with the window.

Iterate over top-level windows

import win32con
import win32gui
import win32process

def get_hwnds_for_pid (pid):
  def callback (hwnd, hwnds):
    if win32gui.IsWindowVisible (hwnd) and win32gui.IsWindowEnabled (hwnd):
      _, found_pid = win32process.GetWindowThreadProcessId (hwnd)
      if found_pid == pid:
        hwnds.append (hwnd)
    return True
    
  hwnds = []
  win32gui.EnumWindows (callback, hwnds)
  return hwnds

if __name__ == '__main__':
  import subprocess
  import time
  notepad = subprocess.Popen ([r"notepad.exe"])
  #
  # sleep to give the window time to appear
  #
  time.sleep (2.0)
  
  for hwnd in get_hwnds_for_pid (notepad.pid):
    print hwnd, "=>", win32gui.GetWindowText (hwnd)
    win32gui.SendMessage (hwnd, win32con.WM_CLOSE, 0, 0)