GetVolumeInformation获取的是文件系统卷序列号,非物理磁盘ID;稳定识别硬盘应优先用WMI的Win32_DiskDrive.SerialNumber,失败后以管理员权限调用IOCTL_STORAGE_QUERY_PROPERTY获取设备描述符序列号。

GetVolumeInformation 获取的是卷序列号,不是物理磁盘 ID
很多人用 GetVolumeInformation 拿到一串数字(比如 0x1a2b3c4d),就以为是硬盘的唯一 ID——其实这是文件系统卷的序列号,重装系统、格式化、甚至用 DiskPart clean 后都会变。它不绑定物理磁盘,也不跨分区稳定。真要识别同一块 SATA/NVMe 硬盘,得绕开文件系统层,直连设备驱动。
WMI 查询 Win32_DiskDrive 是最稳妥的跨版本方案
Windows 自带的 WMI 接口对普通程序权限友好,不需要管理员提权(但部分字段如 SerialNumber 在某些 OEM 机器上可能为空)。关键是要用 Win32_DiskDrive 类,而不是 Win32_Volume 或 Win32_PhysicalMedia(后者在 Win10/11 上常返回空或访问拒绝)。
- 必须初始化 COM:调用
CoInitializeEx(nullptr, COINIT_MULTITHREADED)和CoInitializeSecurity(最低安全配置即可) - 查询语句用
"SELECT SerialNumber, Model, InterfaceType, Size FROM Win32_DiskDrive",SerialNumber字段最接近传统“硬盘序列号” -
Size可辅助去重(多块同型号盘时靠它区分);InterfaceType能筛掉 USB 转接盘(值为 "USB" 的通常不可靠) - 注意:NVMe 盘的
SerialNumber通常有值;SATA 盘取决于固件是否如实上报,有些联想/戴尔机器会返回全空字符串
通过 DeviceIoControl + IOCTL_STORAGE_QUERY_PROPERTY 拿原始设备描述符
如果 WMI 的 SerialNumber 为空,且你有管理员权限,可以打开物理设备句柄(如 \.PhysicalDrive0)并发送 IOCTL_STORAGE_QUERY_PROPERTY。这比 WMI 更底层,但也更易失败:
将提醒同步至 Windows/Outlook 日历。用户提及「提醒我」「设置提醒」「加到日历」「同步到日历」「日程」「calendar」「日历」时触发。支持Microsoft Graph API 设备代码流认证,无需 Web 服务器,直接写入用户 Outlook 日历。
- 必须用
CreateFile以GENERIC_READ和FILE_SHARE_READ | FILE_SHARE_WRITE打开,否则返回ERROR_ACCESS_DENIED - 需要构造
STORAGE_PROPERTY_QUERY,PropertyId设为StorageDeviceProperty,QueryType为PropertyStandardQuery - 返回结构体
STORAGE_DEVICE_DESCRIPTOR中的SerialNumberOffset指向缓冲区内的 ASCII 序列号字符串(需手动拷贝并截断末尾 ) - 某些 SSD(尤其国产品牌)会在该字段填入空格或乱码,建议同时读取
VendorId+ProductId拼接作为 fallback ID
不要依赖 ATA IDENTIFY 或 SMART 数据——兼容性太差
网上有些代码用 DeviceIoControl 发 SMART_RCV_DRIVE_DATA 或直接发 ATA 命令,这类操作在 Win10 1903+ 默认被禁用,除非关闭内核隔离(HVCI)或加驱动签名白名单。普通应用根本走不通,而且不同控制器(Intel RST、AMD RAID、NVMe 驱动)返回格式不一致,解析极易崩溃。
立即学习“C++免费学习笔记(深入)”;
真正稳定的组合只有两个:WMI 查 Win32_DiskDrive.SerialNumber(优先);失败后再用 IOCTL_STORAGE_QUERY_PROPERTY(需 admin)。其余路径要么权限卡死,要么 OEM 不填数据,要么新版 Windows 直接拒交。序列号本身就不保证全局唯一——同一型号批量盘出厂序列号可能只差末位数字,真要做设备绑定,得结合主板 UUID + 磁盘 ID + 加密 nonce 才算稳妥。

















