import hashlib import platform import subprocess import uuid import os from typing import Optional class DeviceIDGenerator: """ Windows设备唯一ID生成器 通过收集多个硬件特征来生成稳定的设备唯一标识符 """ def __init__(self, use_cache: bool = True, cache_file: str = ".device_id"): """ 初始化设备ID生成器 Args: use_cache: 是否使用本地缓存 cache_file: 缓存文件名 """ self.use_cache = use_cache self.cache_file = cache_file def _run_wmic_command(self, command: str) -> Optional[str]: """ 执行WMIC命令并返回结果 Args: command: WMIC命令 Returns: 命令执行结果,失败则返回None """ try: result = subprocess.run( command, shell=True, capture_output=True, text=True, timeout=10 ) if result.returncode == 0 and result.stdout.strip(): return result.stdout.strip() except (subprocess.TimeoutExpired, Exception): pass return None def _get_motherboard_serial(self) -> Optional[str]: """获取主板序列号""" return self._run_wmic_command("wmic baseboard get serialnumber /value") def _get_cpu_id(self) -> Optional[str]: """获取CPU ID""" return self._run_wmic_command("wmic cpu get processorid /value") def _get_bios_serial(self) -> Optional[str]: """获取BIOS序列号""" return self._run_wmic_command("wmic bios get serialnumber /value") def _get_disk_serial(self) -> Optional[str]: """获取系统盘序列号""" return self._run_wmic_command("wmic diskdrive get serialnumber /value") def _get_machine_guid(self) -> Optional[str]: """获取Windows机器GUID""" try: result = subprocess.run( 'reg query "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography" /v MachineGuid', shell=True, capture_output=True, text=True, timeout=10 ) if result.returncode == 0: for line in result.stdout.split('\n'): if 'MachineGuid' in line: return line.split()[-1] except Exception: pass return None def _extract_value(self, wmic_output: str) -> str: """从WMIC输出中提取实际值""" if not wmic_output: return "" lines = wmic_output.split('\n') for line in lines: if '=' in line and not line.strip().endswith('='): return line.split('=', 1)[1].strip() return "" def _collect_hardware_info(self) -> dict: """ 收集硬件信息 Returns: 包含各种硬件信息的字典 """ hardware_info = {} # 主板序列号 motherboard = self._get_motherboard_serial() hardware_info['motherboard'] = self._extract_value(motherboard) if motherboard else "" # CPU ID cpu_id = self._get_cpu_id() hardware_info['cpu'] = self._extract_value(cpu_id) if cpu_id else "" # BIOS序列号 bios = self._get_bios_serial() hardware_info['bios'] = self._extract_value(bios) if bios else "" # 硬盘序列号 disk = self._get_disk_serial() hardware_info['disk'] = self._extract_value(disk) if disk else "" # Windows机器GUID machine_guid = self._get_machine_guid() hardware_info['machine_guid'] = machine_guid if machine_guid else "" # 计算机名称 hardware_info['computer_name'] = platform.node() # MAC地址(作为备用) hardware_info['mac_address'] = ':'.join(['{:02x}'.format((uuid.getnode() >> elements) & 0xff) for elements in range(0, 2*6, 2)][::-1]) return hardware_info def _generate_device_id(self, hardware_info: dict) -> str: """ 基于硬件信息生成设备ID Args: hardware_info: 硬件信息字典 Returns: 32位十六进制设备ID """ # 过滤掉空值,并按键排序确保一致性 filtered_info = {k: v for k, v in hardware_info.items() if v and v.strip()} # 如果没有任何硬件信息,使用MAC地址作为后备方案 if not filtered_info: filtered_info = {'mac_address': hardware_info.get('mac_address', str(uuid.getnode()))} # 将所有信息连接成字符串 info_string = '|'.join(f"{k}:{v}" for k, v in sorted(filtered_info.items())) # 使用SHA256生成哈希值 hash_object = hashlib.sha256(info_string.encode('utf-8')) device_id = hash_object.hexdigest() return device_id def _load_cached_device_id(self) -> Optional[str]: """从缓存文件加载设备ID""" try: if os.path.exists(self.cache_file): with open(self.cache_file, 'r', encoding='utf-8') as f: cached_id = f.read().strip() if len(cached_id) == 64: # SHA256哈希长度 return cached_id except Exception: pass return None def _save_device_id_to_cache(self, device_id: str) -> None: """将设备ID保存到缓存文件""" try: with open(self.cache_file, 'w', encoding='utf-8') as f: f.write(device_id) except Exception: pass def get_device_id(self) -> str: """ 获取设备唯一ID Returns: 64字符的十六进制设备ID """ # 如果启用缓存,先尝试从缓存加载 if self.use_cache: cached_id = self._load_cached_device_id() if cached_id: return cached_id # 收集硬件信息 hardware_info = self._collect_hardware_info() # 生成设备ID device_id = self._generate_device_id(hardware_info) # 保存到缓存 if self.use_cache: self._save_device_id_to_cache(device_id) return device_id def get_device_id_short(self, length: int = 16) -> str: """ 获取短版本的设备ID Args: length: 返回ID的长度 Returns: 指定长度的设备ID """ full_id = self.get_device_id() return full_id[:length] def get_hardware_info(self) -> dict: """ 获取硬件信息(用于调试) Returns: 硬件信息字典 """ return self._collect_hardware_info() # 使用示例 def main(): """使用示例""" # 创建设备ID生成器实例 device_generator = DeviceIDGenerator() # 获取完整设备ID(64字符) device_id = device_generator.get_device_id() print(f"完整设备ID: {device_id}") # 获取短版本设备ID(16字符) short_id = device_generator.get_device_id_short(16) print(f"短设备ID: {short_id}") # 查看硬件信息(调试用) hardware_info = device_generator.get_hardware_info() print("\n硬件信息:") for key, value in hardware_info.items(): print(f" {key}: {value}") if __name__ == "__main__": main()