C/C++運用WMI接口實現(xiàn)查詢系統(tǒng)信息
Windows Management Instrumentation(WMI)是一種用于管理和監(jiān)視Windows
操作系統(tǒng)的框架。它為開發(fā)人員、系統(tǒng)管理員和自動化工具提供了一種標準的接口,通過這個接口,可以獲取有關(guān)計算機系統(tǒng)硬件、操作系統(tǒng)和應(yīng)用程序的信息,以及對系統(tǒng)進行管理和控制的能力。
WMI允許通過編程方式查詢系統(tǒng)信息、監(jiān)視性能、執(zhí)行管理任務(wù)等。它提供了一種統(tǒng)一的方式來訪問和管理Windows操作系統(tǒng)的各個方面,而無需了解底層實現(xiàn)細節(jié)。通過WMI,可以使用各種編程語言(如C#、VBScript、PowerShell等)來執(zhí)行諸如查詢系統(tǒng)信息、監(jiān)控性能、配置系統(tǒng)設(shè)置等任務(wù)。
當需要通過WMI
編程提取參數(shù)時,我們就需要使用WQL(Windows Management Instrumentation Query Language)它是一種查詢語言,專門用于查詢Windows Management Instrumentation (WMI)
數(shù)據(jù)。WMI 是Windows
操作系統(tǒng)中用于管理和監(jiān)視的框架,而WQL
則是用于與WMI
進行交互的查詢語言。
WQL 的語法類似于 SQL(Structured Query Language),使用WQL可以執(zhí)行各種查詢來檢索關(guān)于計算機系統(tǒng)、硬件、軟件和其他管理信息的數(shù)據(jù)。這些查詢可以用于編寫腳本、管理任務(wù)、監(jiān)視性能等。為了方便查詢獲取參數(shù)這里提供一個簡單的查詢工具供大家查詢使用,下載后打開,其默認查詢的是Win32_ComputerSystem
也就是系統(tǒng)的基本參數(shù)信息;
如果我們需要獲取其他信息,比如得到計算機中所安裝的所有Windows服務(wù)信息,可以執(zhí)行SELECT * FROM Win32_Service
語句,當然也有許多其他的通用語句可以讓我們使用,例如如下幾種常用的語句。
查詢所有安裝的軟件
SELECT * FROM Win32_Product
查詢所有邏輯磁盤的信息
SELECT * FROM Win32_LogicalDisk
查詢所有網(wǎng)絡(luò)適配器的信息
SELECT * FROM Win32_NetworkAdapter
查詢操作系統(tǒng)信息
SELECT * FROM Win32_OperatingSystem
查詢所有正在運行的進程
SELECT * FROM Win32_Process
查詢所有用戶賬戶信息
SELECT * FROM Win32_UserAccount
查詢系統(tǒng)啟動項
SELECT * FROM Win32_StartupCommand
查詢物理內(nèi)存
SELECT * FROM Win32_PhysicalMemory
如上圖所示,查詢將返回Win32_Service
類中所有服務(wù)的信息。你可以根據(jù)需要編寫更復(fù)雜的查詢,以滿足特定的管理或監(jiān)視要求。
為了讓讀者更加方便的使用查詢功能,此處我封裝了一個SelectQuerySQL
查詢函數(shù),該函數(shù)需要傳入特定的查詢語句,特定的查詢字段以及返回值緩沖區(qū),此時只需要讀取緩沖區(qū)內(nèi)的數(shù)據(jù)即可得到查詢結(jié)果。
#define _CRT_SECURE_NO_WARNINGS #define _WIN32_DCOM #define _CRT_NONSTDC_NO_DEPRECATE #include <comdef.h> #include <Wbemidl.h> #include <iostream> #include <string> # pragma comment(lib, "wbemuuid.lib") using namespace std; // 去掉字符串中的空格 void Trims(char* data) { int i = -1, j = 0; int ch = ' '; while (data[++i] != '\0') { if (data[i] != ch) { data[j++] = data[i]; } } data[j] = '\0'; } // 通用查詢方法,每次查詢一條 bool SelectQuerySQL(LPCWSTR SQL, LPCWSTR Key, OUT char OutBuf[1024]) { HRESULT hres; CoUninitialize(); hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { return false; } hres = CoInitializeSecurity(0, -1, 0, 0, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, 0, EOAC_NONE, 0); if (FAILED(hres)) { CoUninitialize(); return false; } IWbemLocator* pLoc = NULL; hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); if (FAILED(hres)) { CoUninitialize(); return false; } IWbemServices* pSvc = NULL; hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), 0, 0, 0, 0, 0, 0, &pSvc); if (FAILED(hres)) { pLoc->Release(); CoUninitialize(); return false; } hres = CoSetProxyBlanket(pSvc,RPC_C_AUTHN_WINNT,RPC_C_AUTHZ_NONE,NULL,RPC_C_AUTHN_LEVEL_CALL,RPC_C_IMP_LEVEL_IMPERSONATE,NULL,EOAC_NONE); if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return false; } IEnumWbemClassObject* pEnumerator = NULL; // 執(zhí)行WSQL語句 hres = pSvc->ExecQuery(bstr_t("WQL"),bstr_t(SQL),WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,NULL,&pEnumerator); if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return false; } IWbemClassObject* pclsObj; ULONG uReturn = 0; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (0 == uReturn) { break; } VARIANT vtProp; // 獲取到指定Key字段 hr = pclsObj->Get(Key, 0, &vtProp, 0, 0); // 將獲取到的數(shù)據(jù)返回給OutBuf wcstombs(OutBuf, vtProp.bstrVal, 1024); VariantClear(&vtProp); pclsObj->Release(); } pSvc->Release(); pLoc->Release(); pEnumerator->Release(); CoUninitialize(); return true; }
有了上述函數(shù)的封裝,那么實現(xiàn)查詢就變得很容易了,當我們需要查詢CPU序列號時,可以直接執(zhí)行SELECT * FROM win32_Processor
并取出里面的ProcessorId
字段,使用函數(shù)時可以總結(jié)為如下所示的案例;
int main(int argc, char *argv[]) { char RefBuffer[1024] = { 0 }; bool ref = false; ref = SelectQuerySQL(L"SELECT * FROM win32_Processor", L"ProcessorId", RefBuffer); std::cout << "獲取CPU序列號: " << RefBuffer << std::endl; Trims(RefBuffer); system("pause"); return 0; }
輸出效果如下所示;
根據(jù)這個查詢方法,我們就可以得到系統(tǒng)的各類固件序列號,這對于軟件認證尤為重要;
int main(int argc, char *argv[]) { char RefBuffer[1024] = { 0 }; bool ref = false; ref = SelectQuerySQL(L"SELECT * FROM win32_Processor", L"ProcessorId", RefBuffer); std::cout << "獲取CPU序列號: " << RefBuffer << std::endl; Trims(RefBuffer); ref = SelectQuerySQL(L"SELECT * FROM Win32_BaseBoard", L"SerialNumber", RefBuffer); std::cout << "獲取主板ID號: " << RefBuffer << std::endl; Trims(RefBuffer); ref = SelectQuerySQL(L"SELECT * FROM Win32_BIOS", L"SerialNumber", RefBuffer); std::cout << "獲取BIOS序列號: " << RefBuffer << std::endl; Trims(RefBuffer); ref = SelectQuerySQL(L"SELECT * FROM Win32_PhysicalMemory", L"SerialNumber", RefBuffer); std::cout << "獲取內(nèi)存序列號: " << RefBuffer << std::endl; Trims(RefBuffer); ref = SelectQuerySQL(L"SELECT * FROM Win32_DiskDrive WHERE Index = 0", L"SerialNumber", RefBuffer); Trims(RefBuffer); std::cout << "獲取硬盤序列號: " << RefBuffer << std::endl; system("pause"); return 0; }
輸出效果如下所示;
當然,有時我們也需要一次性輸出多個參數(shù),某些數(shù)據(jù)存在多條記錄,在輸出時也需要增加一些代碼,我們以Win32_LogicalDisk
為例,代碼需要進行一定的改進,在循環(huán)時分別取出不同的字段,此時的查詢函數(shù)需要相應(yīng)的做一些改進,如下是查詢函數(shù)需要變化的位置。
while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (0 == uReturn) { break; } // 輸出盤符字段 VARIANT vtProp_DeviceID; VARIANT vtProp_FreeSpace; VARIANT vtProp_Size; // 獲取到指定Key字段 hr = pclsObj->Get(L"DeviceID", 0, &vtProp_DeviceID, 0, 0); hr = pclsObj->Get(L"FreeSpace", 0, &vtProp_FreeSpace, 0, 0); hr = pclsObj->Get(L"Size", 0, &vtProp_Size, 0, 0); // 轉(zhuǎn)換數(shù)據(jù)為字符串 char x[32], y[32], z[32]; wcstombs(x, vtProp_DeviceID.bstrVal, 32); wcstombs(y, vtProp_FreeSpace.bstrVal, 32); wcstombs(z, vtProp_Size.bstrVal, 32); std::cout << "分區(qū): " << x << std::endl; std::cout << "剩余: " << y << std::endl; std::cout << "容量: " << z << std::endl; // 清理 VariantClear(&vtProp_DeviceID); VariantClear(&vtProp_FreeSpace); VariantClear(&vtProp_Size); pclsObj->Release(); }
此外,在查詢參數(shù)上也應(yīng)該修改為對應(yīng)的SELECT * FROM Win32_LogicalDisk
查詢磁盤;
int main(int argc, char *argv[]) { char RefBuffer[1024] = { 0 }; bool ref = false; ref = SelectQuerySQL(L"SELECT * FROM Win32_LogicalDisk", L"ProcessorId", RefBuffer); Trims(RefBuffer); system("pause"); return 0; }
此時,當再一次運行這段代碼,就可以查詢到當前系統(tǒng)中所有的磁盤信息,如下圖所示;
以上就是C/C++運用WMI接口實現(xiàn)查詢系統(tǒng)信息的詳細內(nèi)容,更多關(guān)于C++ WMI查詢系統(tǒng)信息的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解MFC/C++調(diào)用易語言的整數(shù)型和文本型與VS2010互動
在本篇文章里我們給大家分享了MFC/C++調(diào)用易語言的整數(shù)型和文本型與VS2010互動相關(guān)知識點內(nèi)容,有興趣的朋友們可以參考下。2018-11-11C語言實現(xiàn)在數(shù)組A上有序合并數(shù)組B的方法
這篇文章主要介紹了C語言實現(xiàn)在數(shù)組A上有序合并數(shù)組B的方法,包含了數(shù)組操作的完整實現(xiàn)過程以及相應(yīng)的代碼分析與改進,具有不錯的借鑒價值,需要的朋友可以參考下2014-09-09C語言中計算正弦的相關(guān)函數(shù)總結(jié)
這篇文章主要介紹了C語言中計算正弦的相關(guān)函數(shù)總結(jié),包括正弦和雙曲線正弦以及反正弦的函數(shù),需要的朋友可以參考下2015-08-08C語言實現(xiàn)影院管理系統(tǒng)程序設(shè)計
這篇文章主要為大家詳細介紹了C語言實現(xiàn)影院管理系統(tǒng)程序設(shè)計,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-08-08C語言詳細分析結(jié)構(gòu)體的內(nèi)存對齊規(guī)則
C 數(shù)組允許定義可存儲相同類型數(shù)據(jù)項的變量,結(jié)構(gòu)是 C 編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲不同類型的數(shù)據(jù)項,本篇讓我們來了解C 的結(jié)構(gòu)體內(nèi)存對齊2022-07-07