在C#开发过程中,获取主板序列号这类底层硬件信息常用于软件授权绑定、设备资产管理等场景,WMI(Windows Management Instrumentation)是Windows系统内置的管理框架,提供了统一的接口来查询硬件、系统等各类信息,是实现该需求的高效方式。

WMI基础概念
WMI是Windows系统提供的管理技术,允许应用程序查询和监控系统的配置、状态等信息,它基于通用信息模型(CIM)标准,将系统资源抽象为可查询的对象。在C#中,我们可以通过System.Management命名空间下的类来调用WMI接口,实现硬件信息的读取。
获取主板序列号的实现步骤
1. 添加命名空间引用
首先需要引入System.Management命名空间,该命名空间包含了WMI查询相关的核心类,如果项目默认没有引用对应的程序集,需要手动添加引用。
using System; using System.Management; // 引入WMI相关命名空间
2. 编写查询主板序列号的代码
主板的相关信息存储在WMI的Win32_BaseBoard类中,其中SerialNumber属性就是我们需要的主板序列号,通过ManagementObjectSearcher类执行WMI查询即可获取对应信息。
public string GetMainBoardSerialNumber()
{
string serialNumber = "";
try
{
// 创建WMI查询,查询Win32_BaseBoard类的所有实例
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard");
// 遍历查询结果
foreach (ManagementObject obj in searcher.Get())
{
// 获取SerialNumber属性的值
serialNumber = obj["SerialNumber"]?.ToString();
break; // 通常只有一个主板实例,获取后跳出循环
}
}
catch (Exception ex)
{
Console.WriteLine("获取主板序列号失败:" + ex.Message);
}
return serialNumber;
}
3. 代码调用示例
在控制台程序中调用上述方法,即可输出主板序列号:
class Program
{
static void Main(string[] args)
{
Program p = new Program();
string mainBoardSerial = p.GetMainBoardSerialNumber();
Console.WriteLine("主板序列号为:" + mainBoardSerial);
Console.ReadLine();
}
public string GetMainBoardSerialNumber()
{
string serialNumber = "";
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard");
foreach (ManagementObject obj in searcher.Get())
{
serialNumber = obj["SerialNumber"]?.ToString();
break;
}
}
catch (Exception ex)
{
Console.WriteLine("获取主板序列号失败:" + ex.Message);
}
return serialNumber;
}
}
通过WMI读取其他底层硬件ID
除了主板序列号,我们还可以通过WMI读取其他硬件的ID信息,不同的硬件对应不同的WMI类,以下是常见硬件的查询类和属性对照表:
| 硬件类型 | WMI类 | 对应ID属性 |
|---|---|---|
| CPU | Win32_Processor | ProcessorId |
| 硬盘 | Win32_DiskDrive | SerialNumber |
| 网卡 | Win32_NetworkAdapter | MACAddress |
| BIOS | Win32_BIOS | SerialNumber |
读取CPU ID示例
以下是读取CPU ID的代码示例,逻辑和获取主板序列号类似,只是查询的WMI类和属性不同:
public string GetCpuId()
{
string cpuId = "";
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT ProcessorId FROM Win32_Processor");
foreach (ManagementObject obj in searcher.Get())
{
cpuId = obj["ProcessorId"]?.ToString();
break;
}
}
catch (Exception ex)
{
Console.WriteLine("获取CPU ID失败:" + ex.Message);
}
return cpuId;
}
注意事项
- WMI查询需要程序具有对应的系统权限,部分场景下可能需要以管理员身份运行程序才能正常获取信息。
- 不同厂商的主板可能会存在序列号为空或者返回默认值的情况,实际使用中需要做好异常处理。
- 频繁调用WMI查询可能会影响程序性能,建议将获取到的硬件信息缓存起来,避免重复查询。
- 如果是在.NET Core或者.NET 5及以上版本中使用,需要安装
System.ManagementNuGet包,因为该命名空间不再默认包含在框架中。
常见问题解答
为什么获取到的主板序列号是空的?
可能是主板厂商没有在BIOS中写入序列号,或者当前程序没有足够的权限访问WMI信息,可以尝试以管理员身份运行程序,或者检查主板的BIOS设置。
WMI查询会不会有兼容性问题?
WMI是Windows系统原生支持的功能,在Windows XP及以上版本的系统中都可以使用,但是在非Windows系统中无法使用,如果需要跨平台获取硬件信息,需要采用其他对应平台的实现方案。