windows下用wmi获取磁盘序列号最稳定,通过win32_diskdrive.serialnumber获取出厂硬件序列号(非卷标或guid),需初始化com、处理空值并fallback至pnpdeviceid;win32_volume提供分区路径、容量等信息,须用drivetype=3过滤。

Windows下用WMI获取磁盘序列号和分区信息
直接调用WMI是最稳定的方式,绕过驱动签名和权限限制,且能跨NTFS/FAT32/exFAT获取真实硬件序列号(不是卷标或GUID)。Win32_DiskDrive提供物理磁盘序列号,Win32_Volume提供分区路径、容量、文件系统等。
常见错误是误用Win32_DiskPartition——它不包含序列号;或用GetVolumeInformation只拿到卷序列号(每次格式化重生成),不是硬盘出厂序列号。
- 必须初始化COM:调用
CoInitializeEx(nullptr, COINIT_MULTITHREADED),否则查询失败返回E_ACCESSDENIED - 查询
Win32_DiskDrive时,SerialNumber字段可能为空(部分NVMe或虚拟磁盘不暴露),需 fallback 到PNPDeviceID后半段提取逻辑ID - 查
Win32_Volume时加WHERE DriveType=3过滤掉CD-ROM和网络驱动器,避免返回空结果
Linux下用libudev读取磁盘序列号
Linux没有统一“序列号”概念,/sys/block/*/device/下的serial文件最接近(对应SATA/SCSI的IDENTIFY数据),但NVMe设备需读/sys/block/nvme*/device/nvme*/serial,路径不一致。
别依赖lsblk -o NAME,SERIAL——它实际调用的是udev数据库缓存,重启后可能失效;应直接读/sys文件系统确保实时性。
- 需检查
serial文件是否存在且可读,很多USB转接盘或RAID卡会返回空或0000000000000000 -
udevadm info --name=/dev/sda --query=property输出中,ID_SERIAL是拼接值(vendor+model+serial),ID_SERIAL_SHORT才是纯序列号,注意区分 - 普通用户读
/sys/block/sda/device/serial可能因权限被拒,建议用std::ifstream配合errno == EACCES判断,而非硬加sudo
C++跨平台封装的关键取舍点
没法写一套代码在Windows/Linux都拿到“相同语义”的序列号。Windows的Win32_DiskDrive.SerialNumber是厂商写入的唯一字符串;Linux的serial文件内容取决于内核驱动是否解析了ATA IDENTIFY响应,二者不可互换。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
分区信息倒相对统一:GetVolumeInformation(Win)和statvfs(Linux)都能拿到总/可用空间,但Windows的Win32_Volume还能提供DriveLetter,Linux需自己从/proc/mounts或getmntent解析挂载点。
- 不要试图用MD5哈希序列号做跨平台标识——Linux序列号可能为空,Windows可能含空格或不可见字符
- 若业务只要“区分不同物理盘”,Windows用
PNPDeviceID,Linux用ID_WWN(如果有)更可靠 - 分区大小单位:Windows返回字节数,Linux的
statvfs.f_blocks * f_frsize才是真实字节,别直接用f_blocks * 512
为什么GetDiskFreeSpaceEx不够用
GetDiskFreeSpaceEx只能告诉你某个路径所在卷的剩余空间,完全不涉及磁盘物理属性或分区拓扑。它甚至无法回答“D:和E:是否在同一块物理硬盘上”这种问题。
典型误用场景:想靠它反推序列号——结果发现同一块SSD分了两个区,GetDiskFreeSpaceEx("D:\")和GetDiskFreeSpaceEx("E:\")返回不同lpFreeBytesAvailable,但序列号必须一样。
- 该函数不触发任何磁盘IO,所以快,但信息维度单一
- 传入UNC路径(如
\\server\share)时返回网络共享信息,和本地磁盘序列号无关 - 对BitLocker加密卷,它仍能正常返回空间,但WMI或libudev才能看到底层物理盘是否被加密
实际项目里,序列号常用于软授权绑定,但得接受Linux下部分设备拿不到有效值;分区信息则优先走WMI或libudev,而不是拼凑多个API。真正麻烦的从来不是怎么查,而是查到之后如何定义“同一块盘”——尤其遇到Dell PERC卡、Intel RST或NVMe多命名空间时,序列号和设备路径的关系会突然变得不直观。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










