@@ -61,7 +61,7 @@ def _start_tracking(self):
6161
6262 def _fetch_app_names (self ):
6363 apps = []
64- seen_names = ["AppUsageGUI" , "Python" ]
64+ seen_names = ["AppUsageGUI" , "Python" , "Python3" ]
6565
6666 for process in psutil .process_iter (["pid" , "name" ]):
6767 try :
@@ -133,6 +133,9 @@ def start_filter_reset(self, refresh=False, update_pids=False):
133133 self .temp_reset_thread .start ()
134134
135135 def _reset_excluded_pids (self , refresh , update_pids ):
136+ logger .info (
137+ f"Resetting excluded PIDs (refresh={ refresh } , update_pids={ update_pids } )"
138+ )
136139 global EXCLUDED_APP_PIDS
137140 global INCLUDED_APP_PIDS
138141 EXCLUDED_APP_PIDS = []
@@ -184,30 +187,37 @@ def _update_excluded_apps(self):
184187 def _has_gui (self , process_id ):
185188 if os .name == "nt" :
186189 try :
187- p = psutil .Process (process_id )
188- exe_path = p .exe ().lower ()
189- name = p .name ().lower ()
190-
191- # Known GUI apps in System32 to KEEP
192- GUI_WHITELIST = {
193- "notepad.exe" ,
194- "mspaint.exe" ,
195- "calc.exe" ,
196- "explorer.exe" ,
197- "taskmgr.exe" ,
198- "winver.exe" ,
199- }
190+ # Not the ideal method, but until pywinauto supports free-threaded builds, this is the best we can do
191+ import ctypes
192+ from ctypes import wintypes
200193
201- if (
202- exe_path .startswith ("C:\\ Windows\\ System32\\ " )
203- and name not in GUI_WHITELIST
204- ):
205- logger .warning ("SYSTEM32" )
206- return False
194+ found_window = [False ]
195+
196+ # Define the callback function type
197+ WNDENUMPROC = ctypes .WINFUNCTYPE (
198+ wintypes .BOOL , wintypes .HWND , wintypes .LPARAM
199+ )
200+
201+ def enum_callback (hwnd , lparam ):
202+ # Get window PID
203+ window_pid = wintypes .DWORD ()
204+ ctypes .windll .user32 .GetWindowThreadProcessId (
205+ hwnd , ctypes .byref (window_pid )
206+ )
207207
208- return p .exe ()
208+ # Check if this window belongs to our PID and is visible
209+ if window_pid .value == process_id :
210+ if ctypes .windll .user32 .IsWindowVisible (hwnd ):
211+ found_window [0 ] = True
212+ return False # Stop enumerating
209213
210- except (RuntimeError , psutil .NoSuchProcess , psutil .AccessDenied ):
214+ return True # Continue enumerating
215+
216+ callback = WNDENUMPROC (enum_callback )
217+ ctypes .windll .user32 .EnumWindows (callback , 0 )
218+ return found_window [0 ]
219+
220+ except RuntimeError :
211221 logger .warning (f"Process { process_id } not found or inaccessible" )
212222 return True
213223 elif sys .platform == "darwin" :
0 commit comments