main.py (3149B)
1 import win32com.client 2 import pythoncom 3 import threading 4 import tkinter as tk 5 from tkinter import ttk 6 import time 7 8 9 class USBDeviceDetector(threading.Thread): 10 def __init__(self, update_callback): 11 super().__init__() 12 self.update_callback = update_callback 13 self.running = True 14 self.devices_before = {} 15 16 def run(self): 17 pythoncom.CoInitialize() # Initialize COM in the thread 18 19 # Initialize devices_before in the thread after COM initialization 20 self.devices_before = self.get_pnp_devices() 21 22 while self.running: 23 time.sleep(1) 24 devices_now = self.get_pnp_devices() 25 new_devices = devices_now.keys() - self.devices_before.keys() 26 removed_devices = self.devices_before.keys() - devices_now.keys() 27 28 # Update the GUI if there are changes 29 if new_devices or removed_devices: 30 self.update_callback(new_devices, removed_devices) 31 32 self.devices_before = devices_now 33 34 pythoncom.CoUninitialize() # Uninitialize COM 35 36 def get_pnp_devices(self): 37 wmi = win32com.client.GetObject("winmgmts:") 38 pnp_devices = wmi.InstancesOf("Win32_PnPEntity") 39 return {device.DeviceID: device.Name for device in pnp_devices} 40 41 def stop(self): 42 self.running = False 43 44 45 class USBDeviceLoggerGUI: 46 def __init__(self, root): 47 self.root = root 48 root.title("USBDetective") 49 50 # Configure the grid to expand the cell containing the Treeview widget 51 root.grid_rowconfigure(0, weight=1) 52 root.grid_columnconfigure(0, weight=1) 53 54 # Create a Treeview widget for logging device changes 55 self.log = ttk.Treeview(root, columns=('DeviceID',)) 56 self.log.grid(row=0, column=0, padx=10, pady=10, sticky='nsew') 57 58 # Configure Treeview columns 59 self.log.heading('#0', text='Status') 60 self.log.column('#0', stretch=tk.YES) 61 self.log.heading('DeviceID', text='Device ID') 62 self.log.column('DeviceID', stretch=tk.YES) 63 64 self.log.bind("<Double-1>", self.on_double_click) 65 66 # Start the USB device detection in a separate thread 67 self.detector = USBDeviceDetector(self.log_device_changes) 68 self.detector.start() 69 70 def log_device_changes(self, new_devices, removed_devices): 71 for device_id in new_devices: 72 self.log.insert('', 'end', text='Connected', values=(device_id,)) 73 for device_id in removed_devices: 74 self.log.insert('', 'end', text='Disconnected', values=(device_id,)) 75 76 def on_double_click(self, event): 77 item = self.log.selection()[0] 78 device_id = self.log.item(item, 'values')[0] 79 self.open_device_manager(device_id) 80 81 def open_device_manager(self, device_id): 82 pass 83 84 def on_close(self): 85 # Ensure thread is properly stopped before closing the GUI 86 self.detector.stop() 87 self.detector.join() 88 self.root.destroy() 89 90 91 if __name__ == '__main__': 92 root = tk.Tk() 93 gui = USBDeviceLoggerGUI(root) 94 root.protocol("WM_DELETE_WINDOW", gui.on_close) 95 root.mainloop()