Replace WMI process enumeration with Win32 EnumProcesses (350x faster)
Use PROCESS_QUERY_LIMITED_INFORMATION + QueryFullProcessImageNameW instead of WMI Win32_Process. Reduces process enumeration from ~3s to ~8ms. All user-facing applications are detected; only protected system services are not visible (irrelevant for profile conditions). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -22,19 +22,53 @@ class PlatformDetector:
|
||||
"""Detect running processes and the foreground window's process."""
|
||||
|
||||
def _get_running_processes_sync(self) -> Set[str]:
|
||||
"""Get set of lowercase process names (blocking, call via executor)."""
|
||||
"""Get set of lowercase process names via Win32 EnumProcesses.
|
||||
|
||||
Uses PROCESS_QUERY_LIMITED_INFORMATION + QueryFullProcessImageNameW
|
||||
which is ~300x faster than WMI (~8ms vs ~3s). System services
|
||||
running under protected accounts are not visible, but all
|
||||
user-facing applications are covered.
|
||||
"""
|
||||
if not _IS_WINDOWS:
|
||||
return set()
|
||||
|
||||
try:
|
||||
import pythoncom
|
||||
pythoncom.CoInitialize()
|
||||
psapi = ctypes.windll.psapi
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
|
||||
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
|
||||
|
||||
# Enumerate all PIDs
|
||||
pid_array = (ctypes.wintypes.DWORD * 2048)()
|
||||
cb_needed = ctypes.wintypes.DWORD()
|
||||
psapi.EnumProcesses(
|
||||
ctypes.byref(pid_array), ctypes.sizeof(pid_array),
|
||||
ctypes.byref(cb_needed),
|
||||
)
|
||||
n_pids = cb_needed.value // ctypes.sizeof(ctypes.wintypes.DWORD)
|
||||
|
||||
procs: Set[str] = set()
|
||||
name_buf = ctypes.create_unicode_buffer(512)
|
||||
|
||||
for i in range(n_pids):
|
||||
pid = pid_array[i]
|
||||
if pid == 0:
|
||||
continue
|
||||
handle = kernel32.OpenProcess(
|
||||
PROCESS_QUERY_LIMITED_INFORMATION, False, pid,
|
||||
)
|
||||
if not handle:
|
||||
continue
|
||||
try:
|
||||
import wmi
|
||||
w = wmi.WMI()
|
||||
return {p.Name.lower() for p in w.Win32_Process() if p.Name}
|
||||
buf_size = ctypes.wintypes.DWORD(512)
|
||||
if kernel32.QueryFullProcessImageNameW(
|
||||
handle, 0, name_buf, ctypes.byref(buf_size),
|
||||
):
|
||||
procs.add(os.path.basename(name_buf.value).lower())
|
||||
finally:
|
||||
pythoncom.CoUninitialize()
|
||||
kernel32.CloseHandle(handle)
|
||||
|
||||
return procs
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to enumerate processes: {e}")
|
||||
return set()
|
||||
|
||||
Reference in New Issue
Block a user