David Bandel
David Bandel

Reputation: 3

pywin32 EnumWindows throws "The specified module could not be found" error on Windows 10

I'm trying to write a Python script on Windows 10 that finds a window by its title and then moves/resizes it using pywin32. I have the following code:

import win32gui

# Global variables
found_hwnd = None
partial_title = None  # We'll set this before calling EnumWindows

def enum_windows_callback(hwnd, lParam):
    global found_hwnd, partial_title
    if win32gui.IsWindowVisible(hwnd):
        window_title = win32gui.GetWindowText(hwnd)
        if partial_title and partial_title.lower() in window_title.lower():
            found_hwnd = hwnd
            # Returning False stops the enumeration
            return False
    # Continue enumerating
    return True

def find_window_by_title(title_substring):
    global found_hwnd, partial_title
    found_hwnd = None
    partial_title = title_substring
    win32gui.EnumWindows(enum_windows_callback, None)
    return found_hwnd

def move_and_resize_window(hwnd, x, y, width, height):
    if hwnd is None:
        print("No valid window handle provided.")
        return False
    win32gui.MoveWindow(hwnd, x, y, width, height, True)
    return True

if __name__ == "__main__":
    # Example usage:
    hwnd = find_window_by_title("Cha")

    if hwnd:
        print(f"Found window with HWND: {hwnd}")
        success = move_and_resize_window(hwnd, 100, 100, 800, 600)
        if success:
            print("Window moved and resized successfully.")
        else:
            print("Failed to move and resize the window.")
    else:
        print("No window found containing 'Notepad' in its title.")

When running the above code, sometimes I get an error:

pywintypes.error: (126, 'EnumWindows', 'The specified module could not be found.')

This happens when I try to find a known window by title. Strangely, if I look for a title that doesn't exist, it exits cleanly with "No window found." But for certain existing windows, it throws the error.

What could cause EnumWindows to throw "The specified module could not be found" (error 126) intermittently when using pywin32? Is there something about the environment, the way the callback is structured, or pywin32 setup that I’m missing?

Any insights or troubleshooting steps would be greatly appreciated.

What I've tried:

Upvotes: 0

Views: 85

Answers (1)

CristiFati
CristiFati

Reputation: 41167

It's a mix of issues:

Corrected (relevant parts of) your code.

code00.py:

#!/usr/bin/env python

import sys

import win32api as wapi
import win32gui as wgui
wapi.SetLastError(0)  # Work around PyWin32 bug


def callback_first_window(hwnd, l_param):
    if wgui.IsWindowVisible(hwnd):
        partial_title = l_param[0]
        window_title = wgui.GetWindowText(hwnd)
        if partial_title and partial_title.lower() in window_title.lower():
            print(f"  - callback: [{partial_title.lower()}], [{window_title.lower()}]")
            l_param[1] = hwnd
            wapi.SetLastError(0)
            # Returning False stops the enumeration
            return False
    # Continue enumerating
    return True


def find_window_by_title(title_substring):
    l_param = [title_substring, 0]
    res = wgui.EnumWindows(callback_first_window, l_param)
    return l_param[1]


def main(*argv):
    text = argv[0] if argv else "not existing"
    hwnd = find_window_by_title(text)
    print(f"Window (text: [{text}]): {hwnd}")


if __name__ == "__main__":
    print(
        "Python {:s} {:03d}bit on {:s}\n".format(
            " ".join(elem.strip() for elem in sys.version.split("\n")),
            64 if sys.maxsize > 0x100000000 else 32,
            sys.platform,
        )
    )
    rc = main(*sys.argv[1:])
    print("\nDone.\n")
    sys.exit(rc)

Output:

(py_pc064_03.10_test1_pw32) [cfati@CFATI-5510-0:e:\Work\Dev\StackExchange\StackOverflow\q079262076]> sopr.bat
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###

[prompt]>
[prompt]> dir /b
code00.py

[prompt]>
[prompt]> python ./code00.py xxxxx
Python 3.10.11 (tags/v3.10.11:7d4cc5a, Apr  5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)] 064bit on win32

  - callback: [xxxxx], [administrator: c:\windows\system32\cmd.exe - sopr.bat - python  ./code00.py xxxxx]
Window (text: [xxxxx]): 13179592

Done.


[prompt]>
[prompt]> python ./code00.py
Python 3.10.11 (tags/v3.10.11:7d4cc5a, Apr  5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)] 064bit on win32

Window (text: [not existing]): 0

Done.

Notes:

  • Passing the window text part as a command line argument is a bit tricky (as seen), since the Cmd window will change its title so that it contains the command being run, and as a result the callback will always return that Cmd window (if no other window is enumerated before it)

  • Callback (and find_window_by_title) can be easily modified to return all windows matching the specified criteria, instead of stopping at the 1st

Upvotes: 0

Related Questions