實戰經驗:透過WMI獲取硬體序列號

如何標識一臺機器

在開發中,有時候我們需要獲取唯一標識本機的序列號,你可能會想到如下幾種

1) MAC地址

2) CPU ID

3) 硬碟ID

MAC地址

因為MAC地址可能會被修改,而且本機可能會有多張網絡卡,同時網絡卡的數量會隨著網絡卡被啟用或禁用而發生變化,所以暫時就不考慮使用MAC地址作為本機硬體標識了。

CPU ID

這個看起來不錯,但是有個問題:CPU廠商有時候為了規避隱私問題,會對同一批次的CPU打上同一個ID,這樣就不能透過CPU ID唯一的標識機器了。

硬碟ID

每一塊硬碟在出廠的時候,廠商會燒錄一個唯一的ID到硬碟中,這個標識通常可以獲取到,並且可以作為機器ID,但是在比較老的硬碟上可能沒有這個ID,另外在虛擬機器中,也可能是獲取不到硬碟ID的。哎,這種方法也是個問題。

綜合以上的描述,我建議使用多種方法聯合起來對機器進行標識,防止其中一個標識因無法獲取而無法最終實現硬體唯一性標識。

下面我們透過WMI的方法來獲取硬體序列號,這裡以CPU ID為例。

WMI

WMI(Windows Management Instrumentation,Windows 管理規範)是一項核心的 Windows 管理技術;使用者可以使用 WMI 管理本地和遠端計算機。

WMI初始化

在使用WMI進行WQL語句查詢之前,我們需要對WMI基礎設施進行初始化。一般包含如下幾個步驟:

1) COM庫初始化(CoInitializeEx)

2) COM庫安全機制初始化(CoInitializeSecurity)

3) 建立IWbemLocator介面例項(CoCreateInstance)

4) 連線至WMI服務(ConnectServer)

5) 設定請求代理的安全級別(CoSetProxyBlanket)

以下是具體程式碼片段

實戰經驗:透過WMI獲取硬體序列號

使用WQL進行查詢

WMI支援WQL語句查詢,這個WQL非常類似SQL,例如,查詢CPU資訊的語句如下:

SELECT * FROM win32_Processor

讀取CPU ID的步驟如下

1) 執行WQL查詢語句(ExecQuery)

此呼叫會建立一個IEnumWbemClassObject介面的列舉器例項,後面會用到這個列舉器

2) 列舉CPU個數(Next),返回一個IWbemClassObject物件代表當前CPU

3) 呼叫IWbemClassObject物件的Get方法獲取具體的屬性,例如CPU ID。

4) 釋放IWbemClassObject物件

5) 當列舉完畢,釋放IEnumWbemClassObject物件

具體程式碼片段如下:

實戰經驗:透過WMI獲取硬體序列號

WMI釋放

當不再使用WMI元件的時候,一定要記得釋放相關的介面例項,以及COM庫,避免資源洩漏。

實戰經驗:透過WMI獲取硬體序列號

總結

1) WMI的好處在於統一的介面和呼叫方式,作業系統直接在底層提供了支援,不需要我們深入到硬體層面去了解各種不同的硬體資訊。

2) 不好的地方:WMI呼叫,特別是初始化的時候,需要的時間比較長,這個對於效能敏感及要求快速獲取相關資訊的應用來說,需要慎重考慮。