1. 程式人生 > >Windows客戶端開發--WMI技術介紹

Windows客戶端開發--WMI技術介紹

                     
時光荏苒,六道輪迴。2004年,初中,歐錦賽,希臘神話,17歲的C羅哭成了淚人!2016年,工作,歐洲盃,能否再讓C羅哭成淚人?
  • 1
  • 2
  • 3

想要獲得計算機硬體的詳細資訊,我們可以使用WMI。

今天就作為開篇,談一談什麼是WMI? Windows Management Instrumentation (WMI) is a scalable system management infrastructure that uses a single, consistent, standards-based, extensible, object-oriented interface. WMI provides you with a standard way to interact with system management information and the underlying WMI APIs. WMI is used primarily by system management application developers and administrators to access and manipulate system management information.

The purpose of WMI is to provide a standardized means for managing your computer system, be it a local computer or all the computers in an enterprise. In its simplest terms, management is little more than collecting data about the state of a managed object on the computer system and altering the state of the managed object by changing the data stored about the object. A managed object can be a hardware entity, such as a memory array, port, or disk drive. It can also be a software entity, such as a service, user account, or page file.

WMI can manage the many components of a computer system. In managing a hard disk, you can use WMI to monitor the amount of free space remaining on the disk. You could also use WMI to remotely alter the state of the drive by deleting files, changing file security, or partitioning or formatting the drive.

WMI is not only a powerful tool to collect system information, it is also very easy to use. Existing scripting WMI interface makes it possible to be used for system administrators and web-designers as well as for skilled programmers.

WMI的全稱是Windows Management Instrumentation,即Windows管理工具。它是Windows作業系統中管理資料和操作的基礎模組。我們可以通過WMI指令碼或者應用程式去管理本地或者遠端計算機上的資源。對於VC和彙編程式設計師,想獲取諸如CPU序列號和硬碟序列號等資訊是非常容易的。但是對於VB以及其他一些指令碼語言,想嘗試獲取系統中一些硬體資訊可能就沒那麼容易了。微軟為了能達到一種通用性目的(遵守某些行業標準),設計了WMI。它提供了一個通過作業系統、網路和企業環境去管理本地或遠端計算機的統一介面集。應用程式和指令碼語言使用這套介面集去完成任務,而不是直接通過Windows API。可能有人要問,為什麼不讓設計的指令碼直接在底層使用Windows API,而非要弄個新的技術呢?原因是在目前Windows API中,有些是不支援遠端呼叫或者指令碼呼叫的。這樣通過統一模型的WMI,像VB和指令碼語言就可以去訪問部分系統資訊了。但是並不是所有指令碼語言都可以使用WMI技術:它要支援ActiveX技術。

先上一個官方的例子:

#define _WIN32_DCOM#include <iostream>using namespace std;#include <comdef.h>#include <Wbemidl.h>#pragma comment(lib, "wbemuuid.lib")int main(int argc, char **argv){    HRESULT hres;    // Step 1: --------------------------------------------------    // Initialize COM. ------------------------------------------    hres =  CoInitializeEx(0, COINIT_MULTITHREADED);     if (FAILED(hres))    {        cout << "Failed to initialize COM library. Error code = 0x"             << hex << hres << endl;        return 1;                  // Program has failed.    }    // Step 2: --------------------------------------------------    // Set general COM security levels --------------------------    hres =  CoInitializeSecurity(        NULL,         -1,                          // COM authentication        NULL,                        // Authentication services        NULL,                        // Reserved        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation          NULL,                        // Authentication info        EOAC_NONE,                   // Additional capabilities         NULL                         // Reserved        );    if (FAILED(hres))    {        cout << "Failed to initialize security. Error code = 0x"             << hex << hres << endl;        CoUninitialize();        return 1;                    // Program has failed.    }    // Step 3: ---------------------------------------------------    // Obtain the initial locator to WMI -------------------------    IWbemLocator *pLoc = NULL;    hres = CoCreateInstance(        CLSID_WbemLocator,                     0,         CLSCTX_INPROC_SERVER,         IID_IWbemLocator, (LPVOID *) &pLoc);    if (FAILED(hres))    {        cout << "Failed to create IWbemLocator object."            << " Err code = 0x"            << hex << hres << endl;        CoUninitialize();        return 1;                 // Program has failed.    }    // Step 4: -----------------------------------------------------    // Connect to WMI through the IWbemLocator::ConnectServer method    IWbemServices *pSvc = NULL;    // Connect to the root\cimv2 namespace with    // the current user and obtain pointer pSvc    // to make IWbemServices calls.    hres = pLoc->ConnectServer(         _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace         NULL,                    // User name. NULL = current user         NULL,                    // User password. NULL = current         0,                       // Locale. NULL indicates current         NULL,                    // Security flags.         0,                       // Authority (for example, Kerberos)         0,                       // Context object          &pSvc                    // pointer to IWbemServices proxy         );    if (FAILED(hres))    {        cout << "Could not connect. Error code = 0x"              << hex << hres << endl;        pLoc->Release();             CoUninitialize();        return 1;                // Program has failed.    }    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;    // Step 5: --------------------------------------------------    // Set security levels on the proxy -------------------------    hres = CoSetProxyBlanket(       pSvc,                        // Indicates the proxy to set       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx       NULL,                        // Server principal name        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx       NULL,                        // client identity       EOAC_NONE                    // proxy capabilities     );    if (FAILED(hres))    {        cout << "Could not set proxy blanket. Error code = 0x"             << hex << hres << endl;        pSvc->Release();        pLoc->Release();             CoUninitialize();        return 1;               // Program has failed.    }    // Step 6: --------------------------------------------------    // Use the IWbemServices pointer to make requests of WMI ----    // For example, get the name of the operating system    IEnumWbemClassObject* pEnumerator = NULL;    hres = pSvc->ExecQuery(        bstr_t("WQL"),         bstr_t("SELECT * FROM Win32_OperatingSystem"),        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,         NULL,        &pEnumerator);    if (FAILED(hres))    {        cout << "Query for operating system name failed."            << " Error code = 0x"             << hex << hres << endl;        pSvc->Release();        pLoc->Release();        CoUninitialize();        return 1;               // Program has failed.    }    // Step 7: -------------------------------------------------    // Get the data from the query in step 6 -------------------    IWbemClassObject *pclsObj = NULL;    ULONG uReturn = 0;    while (pEnumerator)    {        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,             &pclsObj, &uReturn);        if(0 == uReturn)        {            break;        }        VARIANT vtProp;        // Get the value of the Name property        hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);        wcout << " OS Name : " << vtProp.bstrVal << endl;        VariantClear(&vtProp);        pclsObj->Release();    }    // Cleanup    // ========    pSvc->Release();    pLoc->Release();    pEnumerator->Release();    CoUninitialize();    return 0;   // Program successfully completed.}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182

步驟: 初始化COM庫 設定程序COM安全資訊   建立程序內COM伺服器   連線WMI名稱空間    設定WMI連線的安全等級    發起WMI請求       清理

接下來的操作就是換湯不換藥。

這裡有個忠告,免費的: 把上面的例子程式碼貼上到自己的工程中時,一定要養成review的習慣,去掉不必要的註釋,不必要的空行。

上面的程式碼中用到了很多api,這裡不再一一贅述,請參閱msdn官方文件。

這裡僅僅是個開始,接下來要發生的事兒:

1 win32控制檯程式中檢視計算機顯示卡的詳細資訊

2 為何在GUI程式中,使用win32控制檯程式同樣的方法,我們無法獲得正確的資訊呢?

3 qt中使用WMI中遇到了哪些坑。

coming soon~~~~~