USBDetective

Log | Files | Refs | README | LICENSE

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()