Skip to content

Commit 2d878c5

Browse files
authored
feat: added back wmi method on Windows as fallback for admin processes (#96)
* build(deps): added back wmi as a dependency * feat(wip): added back wmi method on Windows as fallback for admin processes
1 parent af38b35 commit 2d878c5

File tree

4 files changed

+80
-10
lines changed

4 files changed

+80
-10
lines changed

aw_watcher_window/lib.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,12 @@ def get_current_window_windows() -> Optional[dict]:
3939
from . import windows
4040

4141
window_handle = windows.get_active_window_handle()
42-
app = windows.get_app_name(window_handle)
42+
try:
43+
app = windows.get_app_name(window_handle)
44+
except Exception: # TODO: narrow down the exception
45+
# try with wmi method
46+
app = windows.get_app_name_wmi(window_handle)
47+
4348
title = windows.get_window_title(window_handle)
4449

4550
if app is None:

aw_watcher_window/windows.py

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
from typing import Optional
2-
31
import os
42
import time
3+
from typing import Optional
54

6-
import win32gui
75
import win32api
6+
import win32gui
87
import win32process
8+
import wmi
9+
910

1011
def get_app_path(hwnd) -> Optional[str]:
1112
"""Get application path given hwnd."""
1213
path = None
1314

1415
_, pid = win32process.GetWindowThreadProcessId(hwnd)
15-
process = win32api.OpenProcess(0x0400, False, pid) # PROCESS_QUERY_INFORMATION = 0x0400
16+
process = win32api.OpenProcess(
17+
0x0400, False, pid
18+
) # PROCESS_QUERY_INFORMATION = 0x0400
1619

1720
try:
1821
path = win32process.GetModuleFileNameEx(process, 0)
@@ -21,26 +24,66 @@ def get_app_path(hwnd) -> Optional[str]:
2124

2225
return path
2326

27+
2428
def get_app_name(hwnd) -> Optional[str]:
2529
"""Get application filename given hwnd."""
2630
path = get_app_path(hwnd)
2731

2832
if path is None:
2933
return None
30-
34+
3135
return os.path.basename(path)
3236

37+
3338
def get_window_title(hwnd):
3439
return win32gui.GetWindowText(hwnd)
3540

41+
3642
def get_active_window_handle():
3743
hwnd = win32gui.GetForegroundWindow()
3844
return hwnd
3945

4046

47+
# WMI-version, used as fallback if win32gui/win32process/win32api fails (such as for "run as admin" processes)
48+
49+
c = wmi.WMI()
50+
51+
"""
52+
Much of this derived from: http://stackoverflow.com/a/14973422/965332
53+
"""
54+
55+
56+
def get_app_name_wmi(hwnd) -> Optional[str]:
57+
"""Get application filename given hwnd."""
58+
name = None
59+
_, pid = win32process.GetWindowThreadProcessId(hwnd)
60+
for p in c.query("SELECT Name FROM Win32_Process WHERE ProcessId = %s" % str(pid)):
61+
name = p.Name
62+
break
63+
return name
64+
65+
66+
def get_app_path_wmi(hwnd) -> Optional[str]:
67+
"""Get application path given hwnd."""
68+
path = None
69+
70+
_, pid = win32process.GetWindowThreadProcessId(hwnd)
71+
for p in c.query(
72+
"SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = %s" % str(pid)
73+
):
74+
path = p.ExecutablePath
75+
break
76+
77+
return path
78+
79+
4180
if __name__ == "__main__":
4281
while True:
4382
hwnd = get_active_window_handle()
4483
print("Title:", get_window_title(hwnd))
45-
print("App:", get_app_name(hwnd))
46-
time.sleep(1.0)
84+
print("App: ", get_app_name(hwnd))
85+
print("App (wmi): ", get_app_name_wmi(hwnd))
86+
print("Path: ", get_app_path(hwnd))
87+
print("Path (wmi): ", get_app_path_wmi(hwnd))
88+
89+
time.sleep(1.0)

poetry.lock

Lines changed: 23 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ aw-watcher-window = "aw_watcher_window:main"
1212
python = "^3.8,<3.13"
1313
aw-client = "^0.5"
1414
pywin32 = {version = "306", platform = "win32"}
15+
wmi = {version = "*", platform = "win32"}
1516
pyobjc-framework-ApplicationServices = { version = "*", platform="darwin"}
1617
pyobjc-framework-CoreText = {version = "*", platform="darwin"}
1718
pyobjc-framework-OSAKit = {version = "*", platform="darwin"}

0 commit comments

Comments
 (0)