windows下最可靠方式是通过wmi调用win32_baseboard类获取serialnumber(主板物理序列号)和product(主板型号),二者均无需管理员权限;serialnumber可能为空或"none",需显式判断,且不可与win32_computersystemproduct.uuid混淆。

Windows下用WMI查询Win32_BaseBoard的SerialNumber和Product
Windows平台最可靠的方式是调用WMI(Windows Management Instrumentation),通过Win32_BaseBoard类获取主板序列号(SerialNumber)和型号(常被误当作UUID,实际Product字段对应主板型号,UUID在Win32_ComputerSystemProduct里)。注意:普通用户权限即可查询,无需管理员。
关键点:
-
SerialNumber字段可能为空字符串或"None"——这是厂商未写入SMBIOS导致的,不是代码问题 - 必须初始化COM库:
CoinitializeEx(nullptr, COINIT_MULTITHREADED) - 查询返回的
SerialNumber是BSTR,需用_bstr_t或WideCharToMultiByte转为UTF-8 - 不要用
Win32_BIOS的SerialNumber,它返回的是BIOS序列号,非主板物理序列号
// 示例片段:获取主板序列号
IEnumWbemClassObject* pEnumerator = nullptr;
hr = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT SerialNumber FROM Win32_BaseBoard"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, &pEnumerator);
// 后续遍历pEnumerator获取值...
Linux下读取/sys/class/dmi/id/对应文件
Linux内核2.6+默认启用DMI/SMBIOS支持,主板信息以纯文本形式暴露在/sys/class/dmi/id/目录下。这是最轻量、无依赖的方式,但需注意权限和路径存在性。
常见可读字段:
-
/sys/class/dmi/id/board_serial→ 主板序列号(多数厂商填充) -
/sys/class/dmi/id/product_uuid→ 系统UUID(注意:这是Win32_ComputerSystemProduct.UUID的等价物,非主板UUID;主板本身没有标准UUID字段) -
/sys/class/dmi/id/board_name→ 主板型号
注意事项:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 部分发行版(如某些加固版CentOS)会禁用
CONFIG_DMIID内核选项,导致该目录不存在 - 读取
product_uuid需要root权限(从Linux 5.10起部分发行版放宽,但不可依赖) - 直接
fopen()读取即可,无需libudev或systemd库
macOS无法直接获取主板UUID或序列号
macOS不提供公开API访问主板级硬件标识。IOPlatformUUID(通过ioreg -rd1 -c IOPlatformExpertDevice获取)是系统级UUID,绑定于固件且随重装不变,但它不是主板UUID——苹果设备的主板与逻辑板(Logic Board)高度集成,其序列号由IOPlatformUUID和IOPlatformUUID共同映射,但无标准反查方式。
可行替代方案:
- 用
system_profiler SPHardwareDataType解析Hardware UUID(即IOPlatformUUID)——这是最接近的稳定标识 - 调用
IORegistryEntryCreateCFProperty读取kIOPlatformUUIDKey,需链接IOKit.framework - 不要尝试读取
/dev/disk0或NVRAM变量,既无主板信息,又需特权且不稳定
跨平台时UUID和序列号的本质区别必须厘清
“主板UUID”在SMBIOS规范中并不存在。SMBIOS Type 2(Base Board Information)只定义Serial Number、Product Name、Version等字段。所谓“UUID”实际来自SMBIOS Type 1(System Information)的UUID字段,它属于整机系统,由OEM写入,与主板物理绑定但逻辑上不属于主板实体。
因此实操中必须明确需求:
- 要唯一标识一台物理机器 → 优先用
product_uuid(Linux)、Win32_ComputerSystemProduct.UUID(Windows)、IOPlatformUUID(macOS) - 要匹配维修单上的主板编号 → 只能依赖
board_serial(Linux)、Win32_BaseBoard.SerialNumber(Windows),并接受空值可能 - 任何试图把
product_uuid当作主板UUID来校验硬件更换的行为,都会在双CPU主板、模块化服务器等场景失效
真正难的不是读取,而是理解字段归属层级——拿错层级的ID去比对,调试三天也看不出问题在哪。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










