1

I'm currently trying to get all window handles from a process started by subprocess.Popen looking like this:

def openMP():
    mp_p = os.path.abspath("C:\Program Files (x86)\Mobile Partner\Mobile Partner.exe")
    mp = subprocess.Popen(mp_p, stdin=None, stdout=None, stderr=None, close_fds=True)
    return mp.pid

pid = openMP()
wins = get_hwnds_for_pid(pid)
    for win in wins:
        print(win, "=>", win32gui.GetWindowText(win))

this is using this function (found here):

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

This kind of works but not in the way i would like it too. it returns a single hwnd and i feel it is missing existing child windows. I've tested with the same pid using AutoIts WinList + a simple regex looking like this:

;THIS IS AUTOIT CODE
Local $aWinList = WinList("[REGEXPTITLE:(?i)(.*Mobile Partner.*)]")

and it indeed returns three instead of one hwnd. I would like my python code to get these three Handles aswell.

I've tested around with win32.guiEnumChildWindows but cant get it to work it seems:

parent = hwnd
childs = []
def callback(hwnd,isx):
    print(hwnd)
    print(isx)
    childs.append(hwnd)

ax = win32gui.EnumChildWindows(parent,callback,None)
print(ax)
for child in childs:
    print(child)

sadly this just returns:

pywintypes.error: (2, 'EnumChildWindows', 'The system cannot find the file specified.')

i don't really know why. i'm aware that this is quite complicated but maybe you bright minds can help me.


To sum it up again:

I'm looking for a way to find each and every window handle spawned by a known process id using python (doesn't have to be nativ) on a windows 10 machine.

It should return the same amount of handles AutoIts WinList does.

Lyux
  • 453
  • 1
  • 10
  • 22
  • [`EnumChildWindows`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633494) takes a window handle, not a PID. This should be obvious if you know what a "child window" is actually a child of. It's not a child of a process. – Eryk Sun Jul 19 '18 at 12:42
  • 1
    Also, if you want all windows, why filter out disabled and invisible windows? If invisible windows should actually be included, then you'll also need [`FindWindowEx`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633500) to find all of an application's invisible message-only windows. – Eryk Sun Jul 19 '18 at 12:43
  • @eryksun thanks, quite a good catch on the pid, i altered the part from my code used sadly i'm currently passing a window handle. -> The Error given Still exists. The other catch is gold worth! i really didn't notice i'm filtering the windows, removing this filtering successfully returned 6 handles, i can regex the titles given by `win32gui.GetWindowText(hwnd)` to succesfully return the 3 `hwnd` i want. Thanks alot! – Lyux Jul 19 '18 at 12:54
  • 1
    `EnumChildWindows` would be called for the `hwnd` in the `EnumWindows` callback function, so you'd have an inner loop over the child windows of each top-level window. But bear in mind that it's not called "Windows" for nothing. A top-level window can have many more child windows than at first you might suspect, since practically everything in the GUI is a 'window'. Just as you did with the `EnumWindows` callback, return `True` to continue the enumeration of child windows. Returning a falsey value such as the implicit `None` return value will terminate the enumeration. – Eryk Sun Jul 19 '18 at 13:37
  • https://stackoverflow.com/questions/31278590/get-the-title-of-a-window-of-another-program-using-the-process-name – CristiFati Jul 20 '18 at 17:56

0 Answers0