Windows编程系列:WMI
WMI介绍
Windows Management Instrumentation (WMI) 是基于 Windows 的操作系统上管理数据和操作的基础结构。 用户可以使用 WMI 管理本地和远程计算机。
WMI是Windows操作系统的功能,默认情况下,无须安装就可以使用。某些Provider(提供程序)的安装会由系统配置而定。
快速查看WMI对象内容
打开Powershell,输入
1 Get-WmiObject [WMI Provider]
WMI Provider : WMI的提供程序
如 WIn32_KeyBoard:
WMI的体系结构
WMI提供了一个统一的接口用于从本地或远程计算机系统中获取管理数据。WMI基于COM。(详细的介绍可访问:https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-architecture)
它的体系结构图如下:
WMI的提供程序(Provider)
WMI支持用户自己创建提供程序(Provider),以下列举了操作系统支持的WMI Provider
提供程序 | 描述 |
---|---|
Active Directory 提供程序 | 将 Active Directory 对象映射到 WMI。 通过访问 WMI 中 (LDAP) 命名空间中的轻型目录访问协议,你可以在 Active Directory 中引用或使对象成为别名。 |
BitLocker 驱动器加密 (MANAGE-BDE) 提供程序 | 为硬盘驱动器上的存储区域(由 Win32 _ EncryptableVolume的实例表示,可使用加密来保护)提供配置和管理。 |
BizTalk 提供程序 | 提供对 WMI 类所表示的 BizTalk 管理对象的访问权限。 |
引导配置数据 (BCD) 提供程序 | 通过根 WMI 命名空间中的 BCD 提供程序类提供对启动配置数据的访问 \ 。 有关详细信息,请参阅 BCD 参考。 |
CIMWin32 WMI 提供程序 | 支持在 CimWin32.dll 中实现的类。 其中包括核心 CIM WMI 类、这些类的 Win32 实现和电源管理事件。 |
分布式文件系统 (DFS) 提供程序 | 提供 分布式文件系统 (DFS) 函数,这些函数对多个服务器上的共享进行逻辑分组,并以透明方式将它们链接到单个命名空间中类似于树的结构。 |
分布式文件系统复制 (DFSR) 提供程序 | 创建用于配置和监视 分布式文件系统 (DFS) 服务的工具。 有关详细信息,请参阅 DFSR WMI 类。 |
DNS 提供程序 | 通过使用 Windows Management Instrumentation (WMI) ,管理员和程序员可以配置域名系统 (DNS) 资源记录 (Rr) 和 DNS 服务器。 |
磁盘配额提供程序 | 允许管理员控制每个用户在 NTFS 卷上存储的数据量。 |
事件日志提供程序 | 提供对事件日志服务中数据的访问,以通知事件。 |
Hyper-v WMI 提供程序 (V2) | 使开发人员和脚本编写人员能够快速为虚拟化平台构建自定义工具、实用程序和增强功能。 |
Hyper-v WMI 提供程序 | 使开发人员和脚本编写人员能够快速为虚拟化平台构建自定义工具、实用程序和增强功能。 |
Internet Information Services (IIS) | 公开可用于查询和配置 IIS 元数据库的编程接口。 |
IP 路由提供程序 | 提供网络路由信息。 |
作业对象提供程序 | 提供对命名的内核作业对象上的数据的访问。 |
智能平台管理接口 (IPMI) | 与 WMI IPMI 提供程序一起使用,以便从基板管理控制器 (BMC) 操作向操作系统提供数据。 |
实时通信服务器2003提供程序 | 提供用于创建、注册、配置、管理自定义会话初始协议 (SIP) 应用程序与 实时通信服务器 2003的 WMI 类。 |
网络负载平衡 (NLB) | 允许应用程序通过 WMI 与网络负载平衡群集进行交互。 |
Ping 提供程序 | 提供 WMI 访问标准 ping 命令提供的状态信息。 |
策略提供程序 | 提供对组策略的扩展,并允许在策略应用中进行优化。 |
电源管理事件提供程序 | 向 Win32 _ PowerManagementEvent 类提供信息,以描述通过建模 Windows 电源管理协议而导致电源状态变化的电源管理事件。 |
远程桌面服务 WMI 提供程序 | 在远程桌面服务环境中启用一致的服务器管理。 |
Reporting Services 提供程序 | 定义使您可以编写脚本和代码以修改 Report Server 和报表管理器设置的 WMI 类。 |
(RSoP) 提供程序的策略的结果集 | 提供在假设情况下计划和调试策略设置的方法。 这些方法使管理员能够轻松地确定适用于或将应用于用户或计算机的策略设置的组合。 这称为策略的结果集 (RSoP) 。 有关详细信息,请参阅 关于 RSOP Wmi 方法提供程序 和 rsop wmi 类。 |
安全提供程序 | 检索或更改控制文件、目录和共享的所有权、审核和访问权限的安全设置。 |
服务器群集提供程序 | 定义一组 WMI 类,这些类用于访问群集对象、属性和事件。 |
会话提供程序 | 管理网络会话和连接。 |
卷影复制提供程序 | 为共享文件夹功能的卷影副本提供管理功能。 |
SNMP 提供程序 | 将简单的网络管理协议 (SNMP) 对象(在管理信息基本 (MIB) 架构对象)映射到 WMI CIM 类中。 未预安装此提供程序。 有关详细信息,请参阅 设置 WMI SNMP 环境。 |
System Center Endpoint Protection (SCEP) | 定义用于实现 System Center Endpoint Protection (SCEP) 管理的 WMI 类。 |
系统注册表提供程序 | 允许管理应用程序检索和修改系统注册表中的数据;并在发生更改时接收通知。 64位平台上提供了两个版本的系统注册表提供程序。 |
系统还原提供程序 | 提供配置和使用系统还原功能的类。 有关详细信息,请参阅 配置系统还原 和 系统还原 WMI 类。 |
受信任的平台模块提供程序 | 提供有关安全设备的数据的访问权限(由 Win32 _ TPM的实例表示),这是 Microsoft Windows 可信平台计算机系统的信任的根。 |
Trustmon 提供程序 | 提供有关域信任的访问信息。 |
查看提供程序 | 基于其他类的实例创建新的实例和方法。 64位平台提供了视图提供程序的两个版本。 |
WDM 提供程序 | 提供对符合 Windows 驱动模型 (WDM) 的硬件驱动程序的类、实例、方法和事件的访问。 |
Win32 提供程序 | 提供来自 Windows 系统的访问和更新数据,如环境变量的当前设置和逻辑磁盘的属性。 |
Windows Defender | 定义启用 Windows Defender 管理的 WMI 类。 |
Windows Installer 提供程序 | 提供从 Windows Installer 兼容的应用程序收集的访问信息并使 Windows Installer 过程可远程使用。 |
Windows 产品激活提供程序 | 支持 Windows 产品激活 (WPA) 使用 WMI 接口进行管理,并提供一致的服务器管理。Windows 产品激活在基于 Itanium 的 Windows 操作系统版本上不可用。 |
WMIPerfClass 提供程序 | 创建 WMI 性能计数器类。 WMIPerfInst 提供程序会动态向这些 WMI 性能类提供数据。WMIPerfClass 和 WMIPerfInst 提供程序将替换 ADAP 函数。 |
WmiPerfInst 提供程序 | 从 WMI 性能计数器类 定义动态提供原始和格式化的性能计数器数据。 |
获取WMI数据的步骤
-
通过调用 CoInitializeEx初始化 COM 参数。
-
通过调用 CoInitializeSecurity初始化 COM 进程安全性。
-
通过调用 CoCreateInstance获取 WMI 的初始定位符。
-
通过调用 IWbemLocator:: ConnectServer获取指向本地计算机上根 cimv2 命名空间的 IWbemServices 的指针。
-
设置 IWbemServices proxy security,以便 WMI 服务可以通过调用 CoSetProxyBlanket来模拟客户端。
-
使用 IWbemServices 指针发出 WMI 请求。 再调用 IWbemServices:: ExecQuery来执行查询。
如:
SELECT * FROM Win32_OperatingSystem
-
获取并显示 WQL 查询中的数据。 IEnumWbemClassObject指针链接到查询返回的数据对象,可以通过 IEnumWbemClassObject:: Next方法检索数据对象。 此方法将数据对象链接到传递到方法的 IWbemClassObject 指针。使用 IWbemClassObject:: get 方法从数据对象获取所需的信息。
调用WMI函数的步骤
-
通过调用 CoInitializeEx初始化 COM 参数。
-
通过调用 CoInitializeSecurity初始化 COM 进程安全性。
-
通过调用 CoCreateInstance获取 WMI 的初始定位符。
-
通过调用 IWbemLocator:: ConnectServer获取指向本地计算机上根 cimv2 命名空间的 IWbemServices 的指针。
-
设置 IWbemServices proxy security
-
使用 IWbemServices 指针向 WMI 发出请求。 使用 IWbemServices:: ExecMethod 来调用WMI函数
示例:获取WMI数据
1 #include <iostream> 2 #include <WbemIdl.h> 3 #include<Windows.h> 4 #include <comdef.h> 5 6 #pragma comment(lib,"wbemuuid.lib") 7 8 using namespace std; 9
1 //初始化COM [MTAThread] 2 HRESULT hr; 3 hr = CoInitializeEx(0, COINIT_MULTITHREADED); 4 5 if (FAILED(hr)) 6 { 7 return; 8 } 9 10 //设置COM安全级别 11 hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); 12 13 if (FAILED(hr)) 14 { 15 CoUninitialize(); 16 return; 17 } 18 19 //创建WMI命名空间的连接 20 IWbemLocator* pLoc = NULL; 21 22 hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); 23 24 IWbemServices* pSvc = NULL; 25 26 //连接WMI 27 hr = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc); 28 29 if (FAILED(hr)) 30 { 31 pLoc->Release(); 32 CoUninitialize(); 33 return; 34 } 35 36 //在代理上设置安全级别 37 hr = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); 38 39 if (FAILED(hr)) 40 { 41 pSvc->Release(); 42 pLoc->Release(); 43 44 CoUninitialize(); 45 } 46 47 //查询WMI对象 48 //使用IWbemServices指针创建WMI请求 49 IEnumWbemClassObject* pEnumerator = NULL; 50 pSvc->ExecQuery(bstr_t("WQL"), 51 bstr_t("Select * from win32_OperatingSystem"), 52 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 53 NULL, 54 &pEnumerator); 55 56 if (FAILED(hr)) 57 { 58 pSvc->Release(); 59 pLoc->Release(); 60 CoUninitialize(); 61 return; 62 } 63 64 //获取数据 65 IWbemClassObject* pclsObj = NULL; 66 ULONG uReturn = 0; 67 68 while (pEnumerator) 69 { 70 hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); 71 72 if (0 == uReturn) 73 { 74 break; 75 } 76 77 VARIANT vtProp{}; 78 hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0); 79 80 std::wcout << "OS Name : " << vtProp.bstrVal << std::endl; 81 82 VariantClear(&vtProp); 83 pclsObj->Release(); 84 } 85 86 pSvc->Release(); 87 pLoc->Release(); 88 pEnumerator->Release(); 89 CoUninitialize();
示例:调用WMI函数来禁用/启用网卡
1 /*include 2 *#include <iostream> 3 *#include <WbemIdl.h> 4 *#include<Windows.h> 5 *#include <comdef.h> 6 *#pragma comment(lib,"wbemuuid.lib") 7 *using namespace std; 8 */ 9 10 HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 11 if (FAILED(hr)) 12 { 13 return; 14 } 15 16 if ((FAILED(hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0)))) 17 { 18 return; 19 } 20 21 IWbemLocator* pLocator = NULL; 22 if (FAILED(hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator)))) 23 { 24 return; 25 } 26 27 IWbemServices* pService = NULL; 28 hr = pLocator->ConnectServer(_bstr_t("root\\CIMV2"), NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService); 29 if (FAILED(hr)) 30 { 31 pLocator->Release(); 32 return; 33 } 34 35 IEnumWbemClassObject* pEnumerator = NULL; 36 hr = pService->ExecQuery(_bstr_t("WQL"), _bstr_t("SELECT * FROM Win32_NetworkAdapter WHERE Name Like 'Intel(R) Ethernet Connection (2) I219-V'"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator); 37 if (FAILED(hr)) 38 { 39 pLocator->Release(); 40 pService->Release(); 41 return; 42 } 43 44 IWbemClassObject* clsObj = NULL; 45 int numElems; 46 while ((hr = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE) 47 { 48 if (FAILED(hr)) 49 break; 50 51 VARIANT vtPath; 52 VariantInit(&vtPath); 53 if (FAILED(clsObj->Get(L"__Path", 0, &vtPath, NULL, NULL))) 54 { 55 cout << "Object has no __Path!" << endl; 56 clsObj->Release(); 57 continue; 58 } 59 60 IWbemClassObject* pResult = NULL; 61 //禁用 62 hr = pService->ExecMethod(vtPath.bstrVal, _bstr_t("Disable"), 0, NULL, NULL, &pResult, NULL); 63 if (FAILED(hr)) 64 cout << "Unable to set the default printer: " << std::hex << hr << endl; 65 else 66 { 67 VARIANT vtRet; 68 VariantInit(&vtRet); 69 if (FAILED(hr = pResult->Get(L"ReturnValue", 0, &vtRet, NULL, 0))) 70 cout << "Unable to get return value of call: " << std::hex << hr << endl; 71 else 72 cout << "Method returned: " << vtRet.intVal << endl; 73 74 VariantClear(&vtRet); 75 pResult->Release(); 76 } 77 78 VariantClear(&vtPath); 79 clsObj->Release(); 80 } 81 82 pEnumerator->Release(); 83 pService->Release(); 84 pLocator->Release();
示例:调用WMI函数来创建进程
1 HRESULT hr; 2 hr = CoInitializeEx(0, COINIT_MULTITHREADED); 3 if (FAILED(hr)) 4 { 5 return; 6 } 7 8 hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); 9 if (FAILED(hr)) 10 { 11 CoUninitialize(); 12 return; 13 } 14 15 IWbemLocator* pLoc = NULL; 16 hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); 17 if (FAILED(hr)) 18 { 19 CoUninitialize(); 20 return; 21 } 22 23 IWbemServices* pSvc = NULL; 24 hr = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0,0, &pSvc); 25 if (FAILED(hr)) 26 { 27 pLoc->Release(); 28 CoUninitialize(); 29 return; 30 } 31 32 hr = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); 33 if (FAILED(hr)) 34 { 35 pSvc->Release(); 36 pLoc->Release(); 37 CoUninitialize(); 38 return; 39 } 40 41 BSTR methodName = SysAllocString(L"Create"); 42 BSTR className = SysAllocString(L"Win32_Process"); 43 44 IWbemClassObject* pClass = NULL; 45 hr = pSvc->GetObjectW(className, 0, NULL, &pClass, NULL); 46 47 IWbemClassObject* pInParamDefinition = NULL; 48 hr = pClass->GetMethod(methodName, 0, &pInParamDefinition, NULL); 49 50 IWbemClassObject* pClassInstance = NULL; 51 hr = pInParamDefinition->SpawnInstance(0, &pClassInstance); 52 53 VARIANT varCommand; 54 VariantInit(&varCommand); 55 varCommand.vt = VT_BSTR; 56 varCommand.bstrVal = _bstr_t(L"notepad.exe"); 57 58 hr = pClassInstance->Put(L"CommandLine", 0, &varCommand, 0); 59 60 IWbemClassObject* pOutParams = NULL; 61 hr = pSvc->ExecMethod(className, methodName, 0, NULL, pClassInstance, &pOutParams, NULL); 62 63 if (FAILED(hr)) 64 { 65 VariantClear(&varCommand); 66 SysFreeString(className); 67 SysFreeString(methodName); 68 pClass->Release(); 69 pClassInstance->Release(); 70 pInParamDefinition->Release(); 71 pOutParams->Release(); 72 pSvc->Release(); 73 pLoc->Release(); 74 CoUninitialize(); 75 return; 76 } 77 78 VARIANT varReturnValue; 79 VariantInit(&varReturnValue); 80 hr = pOutParams->Get(BSTR(L"ReturnValue"), 0, &varReturnValue, NULL, 0); 81 82 if (SUCCEEDED(hr)) 83 { 84 VariantClear(&varReturnValue); 85 } 86 VariantClear(&varCommand); 87 SysFreeString(className); 88 SysFreeString(methodName); 89 pClass->Release(); 90 pClassInstance->Release(); 91 pInParamDefinition->Release(); 92 pOutParams->Release(); 93 pLoc->Release(); 94 pSvc->Release(); 95 CoUninitialize();
示例代码
https://github.com/zhaotianff/WindowsProgramming/tree/master/WMI