snapshot of https://github.com/ActivityWatch/aw-watcher-window.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Build / test on ubuntu-latest (py-3.9) (push) Failing after 2m36s
Build / typecheck (push) Successful in 1m38s
Build / test on macos-latest (py-3.9) (push) Has been cancelled
Build / test on windows-latest (py-3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Failing after 1s
Some checks failed
Build / test on ubuntu-latest (py-3.9) (push) Failing after 2m36s
Build / typecheck (push) Successful in 1m38s
Build / test on macos-latest (py-3.9) (push) Has been cancelled
Build / test on windows-latest (py-3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Failing after 1s
This commit is contained in:
89
aw_watcher_window/windows.py
Normal file
89
aw_watcher_window/windows.py
Normal file
@@ -0,0 +1,89 @@
|
||||
import os
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
import win32api
|
||||
import win32gui
|
||||
import win32process
|
||||
import wmi
|
||||
|
||||
|
||||
def get_app_path(hwnd) -> Optional[str]:
|
||||
"""Get application path given hwnd."""
|
||||
path = None
|
||||
|
||||
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
||||
process = win32api.OpenProcess(
|
||||
0x0400, False, pid
|
||||
) # PROCESS_QUERY_INFORMATION = 0x0400
|
||||
|
||||
try:
|
||||
path = win32process.GetModuleFileNameEx(process, 0)
|
||||
finally:
|
||||
win32api.CloseHandle(process)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def get_app_name(hwnd) -> Optional[str]:
|
||||
"""Get application filename given hwnd."""
|
||||
path = get_app_path(hwnd)
|
||||
|
||||
if path is None:
|
||||
return None
|
||||
|
||||
return os.path.basename(path)
|
||||
|
||||
|
||||
def get_window_title(hwnd):
|
||||
return win32gui.GetWindowText(hwnd)
|
||||
|
||||
|
||||
def get_active_window_handle():
|
||||
hwnd = win32gui.GetForegroundWindow()
|
||||
return hwnd
|
||||
|
||||
|
||||
# WMI-version, used as fallback if win32gui/win32process/win32api fails (such as for "run as admin" processes)
|
||||
|
||||
c = wmi.WMI()
|
||||
|
||||
"""
|
||||
Much of this derived from: http://stackoverflow.com/a/14973422/965332
|
||||
"""
|
||||
|
||||
|
||||
def get_app_name_wmi(hwnd) -> Optional[str]:
|
||||
"""Get application filename given hwnd."""
|
||||
name = None
|
||||
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
||||
for p in c.query("SELECT Name FROM Win32_Process WHERE ProcessId = %s" % str(pid)):
|
||||
name = p.Name
|
||||
break
|
||||
return name
|
||||
|
||||
|
||||
def get_app_path_wmi(hwnd) -> Optional[str]:
|
||||
"""Get application path given hwnd."""
|
||||
path = None
|
||||
|
||||
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
||||
for p in c.query(
|
||||
"SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = %s" % str(pid)
|
||||
):
|
||||
path = p.ExecutablePath
|
||||
break
|
||||
|
||||
return path
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
while True:
|
||||
hwnd = get_active_window_handle()
|
||||
print("Title:", get_window_title(hwnd))
|
||||
print("App: ", get_app_name(hwnd))
|
||||
print("App (wmi): ", get_app_name_wmi(hwnd))
|
||||
print("Path: ", get_app_path(hwnd))
|
||||
print("Path (wmi): ", get_app_path_wmi(hwnd))
|
||||
|
||||
time.sleep(1.0)
|
||||
Reference in New Issue
Block a user