准备工作
在Windows系统中,U盘是常见的外部存储设备,很多情况下需要对U盘进行检测。本篇文章将介绍如何使用Python编写一个U盘检测程序,实时检测U盘的插入和拔出事件,并在Windows系统托盘图标中显示检测到的信息。
安装Python
在开始之前,需要安装Python环境。在Windows系统上,可以从Python官网下载安装程序,并按照提示进行安装。
安装PyQt5
PyQt5是一个Python编写的GUI库,用于创建桌面应用程序。在本篇文章中,我们将使用PyQt5创建系统托盘图标。可以使用以下命令安装PyQt5:
pip install PyQt5
客户端程序
客户端程序主要用于检测 U 盘插入和拔出事件,并将消息发送给服务器端。下面是客户端程序的主要步骤:
- 导入必要的模块,如 socket 和 win32api 等。
- 创建一个 WMI 对象,用于监控系统中的 USB 设备。
- 创建一个 socket 连接,用于与服务器端通信。
- 在无限循环中,每隔一段时间检测一次 USB 设备的状态,即获取当前所有 USB 设备的设备 ID。
- 将当前的设备 ID 与上一次检测的设备 ID 进行比较,以检测 U 盘插入和拔出事件。
- 如果检测到 U 盘插入或拔出,则向服务器端发送消息,提示 U 盘的状态。
- 关闭 socket 连接。
import socket
import wmi
import win32api
def monitor_usb():
# 创建 WMI 对象,用于监控系统中的 USB 设备
wmi_obj = wmi.WMI()
# 创建 socket 连接,用于与服务器端通信
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('服务器端IP地址', 12345))
# 获取当前所有 USB 设备的设备 ID
last_usb_devices = get_usb_devices(wmi_obj)
# 不断检测 USB 设备状态
while True:
# 获取当前所有 USB 设备的设备 ID
current_usb_devices = get_usb_devices(wmi_obj)
# 检测 U 盘插入和拔出事件
message = detect_usb_change(last_usb_devices, current_usb_devices)
# 如果检测到 U 盘插入或拔出,则向服务器端发送消息
if message:
client_socket.send(message.encode())
# 更新上一次检测的设备 ID
last_usb_devices = current_usb_devices
# 休眠一段时间,再进行下一次检测
win32api.Sleep(1000)
# 关闭 socket 连接
client_socket.close()
def get_usb_devices(wmi_obj):
# 获取当前所有 USB 设备的设备 ID
usb_devices = wmi_obj.Win32_PnPEntity(ConfigManagerErrorCode=0)
usb_device_ids = [device.DeviceID for device in usb_devices if 'USB' in device.PNPDeviceID]
return usb_device_ids
def detect_usb_change(last_usb_devices, current_usb_devices):
# 检测 U 盘插入和拔出事件
message = ''
for device in last_usb_devices:
if device not in current_usb_devices:
message = 'U盘已拔出'
break
for device in current_usb_devices:
if device not in last_usb_devices:
message = 'U盘已插入'
break
return message
if __name__ == '__main__':
monitor_usb()
服务器端程序
- 创建一个socket连接,用于接收来自客户端电脑的消息。
- 创建系统托盘图标,用于显示U盘检测到的信息。
- 监听来自客户端电脑的消息,并在主机上输出提示信息。
- 更新系统托盘图标以显示U盘检测到的信息。
- 启动程序并开始检测U盘。
import socket
import struct
import os
import sys
import threading
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMenu, QAction
class Server:
def __init__(self):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind(('0.0.0.0', 9999))
self.server_socket.listen(5)
self.connected_clients = {}
self.tray_icon = QSystemTrayIcon()
self.tray_icon.setIcon(QIcon('icon.png'))
self.tray_icon.setToolTip('U盘检测')
menu = QMenu()
quit_action = QAction("退出", self)
quit_action.triggered.connect(self.exit_server)
menu.addAction(quit_action)
self.tray_icon.setContextMenu(menu)
self.tray_icon.show()
def start(self):
threading.Thread(target=self.accept_connections).start()
def accept_connections(self):
while True:
client_socket, addr = self.server_socket.accept()
threading.Thread(target=self.handle_client_connection, args=(client_socket, addr)).start()
def handle_client_connection(self, client_socket, addr):
print(f"New client connected from {addr}")
while True:
try:
data = client_socket.recv(1024)
if not data:
break
message_type = struct.unpack('i', data[:4])[0]
if message_type == 0: # U盘插入事件
drive_name = data[4:].decode('utf-8')
print(f"U盘插入:{drive_name}")
self.tray_icon.showMessage('U盘检测', f"{drive_name} 已插入")
self.connected_clients[addr] = drive_name
self.send_drive_info()
elif message_type == 1: # U盘拔出事件
drive_name = self.connected_clients[addr]
print(f"U盘拔出:{drive_name}")
self.tray_icon.showMessage('U盘检测', f"{drive_name} 已拔出")
self.connected_clients.pop(addr)
self.send_drive_info()
except:
self.connected_clients.pop(addr)
print(f"Client {addr} disconnected")
def exit_server(self):
self.server_socket.close()
self.tray_icon.hide()
QApplication.quit()
if __name__ == '__main__':
app = QApplication(sys.argv)
server = Server()
server.start()
sys.exit(app.exec_())