【Delphi】获取电脑唯一码(一机一码)
        
在日常开发中,可能需要获取每台设备的一个唯一码,那么如何获取每台设备的唯一码呢?一般的做法是获取系统唯一的序列号之类,比如硬盘序列号、CPU序列号、系统ID等等,因为每个电脑的序列号不一定一样(不排除有完全一样的,例如拷贝的虚拟机等),所以想要绝对的不一样也有一定的困难。
那么问题来了,如何获取诸如硬盘序列号、CPU序列号或者硬盘容量等呢?有多种方法,比如使用三方的控件,本文介绍的方法不适用第三方控件,直接使用windows的WMI框架来获取。
下面先介绍下WMI,然后提供一个通过WMI实现获取电脑唯一码的程序。
Windows Management Instrumentation(WMI,Windows 管理规范)是微软推出的一套用于管理 Windows 系统及应用程序的标准化接口和技术,基于分布式管理任务组(DMTF)的通用信息模型(CIM)标准,提供了统一的方式来查询、配置、监控和控制系统资源。
一、WMI 的核心组成
-  
CIM 对象管理器(CIMOM)WMI 的核心服务(
winmgmt服务),负责处理 WMI 请求、管理 CIM 对象库(存储系统资源的元数据),并协调与底层系统的交互。 -  
WMI 命名空间(Namespace)用于组织和隔离管理对象的逻辑容器,类似文件系统的目录。常用命名空间:
root\cimv2:最常用,包含操作系统、硬件、软件等核心管理对象(如进程、服务、磁盘)。root\subscription:用于 WMI 事件订阅(如监控进程创建、服务启动)。root\securitycenter2:系统安全相关信息(如防火墙、 antivirus 状态)。
 -  
WMI 类(Class)描述可管理资源的模板,每个类对应一类系统资源(如
Win32_Process对应进程,Win32_Service对应服务)。类包含属性(资源的特征,如Name、ProcessId)和方法(可执行的操作,如Create创建进程、StopService停止服务)。 -  
WQL 查询语言WMI 查询语言(WMI Query Language),语法类似 SQL,用于从 WMI 类中查询对象。例如:
wql
SELECT Name, ProcessId FROM Win32_Process WHERE Name = 'notepad.exe' 
二、WMI 的核心功能
-  
系统信息查询获取硬件(CPU、内存、磁盘、网络适配器)、软件(进程、服务、安装的程序)、操作系统(版本、启动时间、用户)等信息。
 -  
系统配置管理远程或本地修改系统设置,如启动 / 停止服务、创建 / 终止进程、修改注册表、配置网络适配器等。
 -  
事件监控与响应订阅系统事件(如进程创建、服务状态变化、磁盘空间不足),并触发自定义操作(如日志记录、自动修复)。
 -  
远程管理通过网络远程管理其他 Windows 设备(需权限配置),支持跨域、防火墙穿透(基于 DCOM 或 WS-Management 协议)。
 
三、WMI 的典型应用场景
1. 系统监控与诊断
- 硬件监控:查询 CPU 使用率(
Win32_Processor.LoadPercentage)、内存占用(Win32_PhysicalMemory)、磁盘空间(Win32_LogicalDisk.FreeSpace)等,用于性能分析或告警。 - 软件监控:实时监控进程启动 / 退出(通过
Win32_ProcessTrace事件类)、服务状态(Win32_Service.State),排查异常程序。 
2. 批量管理与自动化
- 企业级设备管理:通过脚本(PowerShell/VBScript)或工具批量查询域内所有计算机的硬件配置(如是否安装某型号显卡)、软件版本(如 Office 版本)。
 - 自动化运维:编写脚本自动执行重复性任务,例如: 
- 停止所有名为 “testService” 的服务:
Get-WmiObject Win32_Service -Filter "Name='testService'" | Invoke-WmiMethod -Name StopService(PowerShell)。 - 远程在多台计算机上创建文件夹:调用
Win32_FileSystemObject的CreateFolder方法。 
 - 停止所有名为 “testService” 的服务:
 
3. 安全审计与日志
- 进程审计:记录所有新启动的进程(通过
Win32_Process的Create事件),追踪可疑程序。 - 权限检查:查询用户组信息(
Win32_Group)、登录会话(Win32_LogonSession),审计未授权访问。 
4. 开发集成
- 应用程序扩展:在 C++/C#/Delphi 等语言中调用 WMI 接口,让程序获取系统信息(如在安装程序中检查磁盘空间是否足够)。
 - 设备驱动管理:查询即插即用设备(
Win32_PnPEntity),开发硬件监控工具。 
四、WMI 的使用工具与方式
-  
命令行工具
wmic:Windows 命令行 WMI 客户端,支持直接执行 WQL 查询。例如:cmd
wmic process where "name='notepad.exe'" get name, processid # 查询记事本进程 wmic service where "state='running'" get name, displayname # 查询运行中的服务- PowerShell:更强大的 WMI 交互工具,通过
Get-WmiObject(旧)或Get-CimInstance(新) cmdlet 操作。 
 -  
脚本语言
- VBScript:通过
GetObject("winmgmts:")连接 WMI 服务,适合编写简单管理脚本。 - PowerShell:原生支持 WMI/CIM,语法更简洁,例如: 
powershell
# 获取所有物理磁盘大小 Get-CimInstance -ClassName Win32_DiskDrive | Select-Object Model, Size 
 - VBScript:通过
 -  
编程语言
- C#:通过
System.Management命名空间(如ManagementObjectSearcher类)调用 WMI。 - Delphi:通过
ISWbemLocator、ISWbemServices等 COM 接口操作(如前文示例)。 - C++:使用 WMI C API(如
IWbemLocator接口)。 
 - C#:通过
 -  
图形化工具
- WMI Explorer:第三方工具,可视化浏览 WMI 命名空间、类、属性和方法,适合学习和调试。
 - 计算机管理:Windows 自带工具(
compmgmt.msc),通过 “WMI 控制” 管理 WMI 配置(如安全权限)。 
 
五、WMI 的优缺点
-  
优点:
- 标准化:基于 CIM 标准,接口统一,无需针对不同硬件 / 软件编写专用代码。
 - 功能全面:覆盖系统管理的几乎所有场景(硬件、软件、事件、配置)。
 - 远程能力:支持跨网络管理,适合企业级批量操作。
 
 -  
缺点:
- 复杂度高:类和属性繁多,初学者需花时间学习(可参考微软 WMI 类文档)。
 - 性能开销:复杂查询或大量对象遍历可能占用较多系统资源。
 - 安全风险:若配置不当,可能被恶意利用(如远程执行命令),需严格控制 WMI 权限。
 
 
六、总结
WMI 是 Windows 系统管理的核心技术,通过统一的接口和查询语言,实现了对系统资源的全方位管理。无论是日常运维、批量管理、应用程序开发还是安全审计,WMI 都能提供强大的支持。掌握 WMI 的使用,能显著提升 Windows 系统管理的效率和自动化水平。
七、Delphi 样例说明
function Get_Win32_Item_Value(Win32_ClassName,ItemName : string) : string;
varFSWbemLocator : OleVariant;FWMIService   : OleVariant;FWbemObjectSet: OleVariant;FWbemObject   : OleVariant;oEnum         : IEnumvariant;QueryStr      : string;iValue        : LongWord;OleValue      : OleVariant;i             : Integer;
begin//初始化数据if not VarIsClear(FSWbemLocator)  then FSWbemLocator := Null;if not VarIsClear(FWMIService)    then FWMIService := Null;if not VarIsClear(FWbemObjectSet) then FWbemObjectSet := Null;if not VarIsClear(FWbemObject)    then FWbemObject := Null;CoInitialize(nil);tryFSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');FWMIService   := FSWbemLocator.ConnectServer('localhost','root\CIMV2','','');QueryStr      := 'SELECT ' + ItemName + ' FROM ' + Win32_ClassName;FWbemObjectSet:= FWMIService.ExecQuery(QueryStr,'WQL',0,Null);oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVARIANT;while oEnum.Next(1,FWbemObject,iValue) = S_OK dobeginif iValue <> 1 then Break;OleValue := FWbemObject.Properties_.Item(ItemName);  //取得返回的属性值if VarIsNull(OleValue) thenResult := 'NULL'elseif VarIsArray(OleValue) thenbeginResult := '';for I := VarArrayLowBound(Result, 1) to VarArrayHighBound(Result, 1) doResult := Result + ' | ' + VarToStr(VarArrayGet(OleValue,[i]));endelsebeginResult := VarToStr(OleValue);if varType(OleValue) = varDispatch then   //日期型Result := Result.Substring(0,14);end;//只需要循环一次,直接退出Break;end;finallyCoUninitialize;end;
end;
 
八、完整代码
EXE执行程序
EXE + 源代码
