3094 words
15 minutes
Windows WMI & System Management: Complete Administrator's Guide

Windows WMI & System Management: Complete Administrator’s Guide#

Windows Management Instrumentation (WMI) is Microsoft’s implementation of Web-Based Enterprise Management (WBEM) for managing Windows systems. This guide covers WMI programming, system monitoring, and advanced management techniques.

Why WMI Programming Matters#

  • System Monitoring: Real-time system health and performance
  • Remote Management: Managing multiple Windows systems
  • Automation: PowerShell and scripting integration
  • Enterprise Tools: Building management applications

WMI Architecture#

graph TB
Apps[Management Applications]
WMI[WMI Service]
Providers[WMI Providers]
CIM[CIM Repository]
WinAPI[Windows APIs]
Hardware[System Hardware]
Apps --> WMI
WMI --> Providers
WMI --> CIM
Providers --> WinAPI
WinAPI --> Hardware

1. WMI Programming with C++#

WMI Client Framework#

// Complete WMI Management Framework
#include <windows.h>
#include <wbemidl.h>
#include <comutil.h>
#include <iostream>
#include <string>
#include <vector>
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "comsuppw.lib")
class WMIManager {
private:
IWbemLocator* m_pLocator;
IWbemServices* m_pServices;
bool m_initialized;
std::wstring m_namespace;
public:
WMIManager() : m_pLocator(nullptr), m_pServices(nullptr),
m_initialized(false), m_namespace(L"root\\cimv2") {}
~WMIManager() {
Cleanup();
}
// Initialize WMI connection
HRESULT Initialize(const std::wstring& computerName = L".",
const std::wstring& userName = L"",
const std::wstring& password = L"") {
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hr)) {
return hr;
}
// Set COM security levels
hr = CoInitializeSecurity(
NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_CONNECT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, NULL);
if (FAILED(hr)) {
CoUninitialize();
return hr;
}
// Create WbemLocator object
hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID*)&m_pLocator);
if (FAILED(hr)) {
CoUninitialize();
return hr;
}
// Connect to WMI namespace
std::wstring connectionString = L"\\\\" + computerName + L"\\" + m_namespace;
hr = m_pLocator->ConnectServer(
_bstr_t(connectionString.c_str()),
userName.empty() ? nullptr : _bstr_t(userName.c_str()),
password.empty() ? nullptr : _bstr_t(password.c_str()),
0, NULL, 0, 0, &m_pServices);
if (FAILED(hr)) {
m_pLocator->Release();
CoUninitialize();
return hr;
}
// Set security levels on proxy
hr = CoSetProxyBlanket(m_pServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE);
if (SUCCEEDED(hr)) {
m_initialized = true;
}
return hr;
}
// Execute WMI query
std::vector<std::map<std::wstring, _variant_t>> Query(const std::wstring& query) {
std::vector<std::map<std::wstring, _variant_t>> results;
if (!m_initialized) {
return results;
}
IEnumWbemClassObject* pEnumerator = nullptr;
HRESULT hr = m_pServices->ExecQuery(
_bstr_t(L"WQL"), _bstr_t(query.c_str()),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL, &pEnumerator);
if (FAILED(hr)) {
return results;
}
IWbemClassObject* pclsObj = nullptr;
ULONG uReturn = 0;
while (pEnumerator) {
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (uReturn == 0) break;
std::map<std::wstring, _variant_t> objectData;
// Get all properties
hr = pclsObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
if (SUCCEEDED(hr)) {
BSTR propertyName = nullptr;
VARIANT propertyValue;
CIMTYPE propertyType;
LONG flavor;
while (pclsObj->Next(0, &propertyName, &propertyValue,
&propertyType, &flavor) == WBEM_S_NO_ERROR) {
objectData[std::wstring(propertyName)] = _variant_t(propertyValue);
SysFreeString(propertyName);
VariantClear(&propertyValue);
}
pclsObj->EndEnumeration();
}
results.push_back(objectData);
pclsObj->Release();
}
pEnumerator->Release();
return results;
}
// Get single property value
_variant_t GetProperty(const std::wstring& className,
const std::wstring& propertyName,
const std::wstring& whereClause = L"") {
std::wstring query = L"SELECT " + propertyName + L" FROM " + className;
if (!whereClause.empty()) {
query += L" WHERE " + whereClause;
}
auto results = Query(query);
if (!results.empty() && results[0].find(propertyName) != results[0].end()) {
return results[0][propertyName];
}
return _variant_t();
}
// Set property value (for writable properties)
HRESULT SetProperty(const std::wstring& instancePath,
const std::wstring& propertyName,
const _variant_t& value) {
if (!m_initialized) {
return E_FAIL;
}
IWbemClassObject* pInstance = nullptr;
HRESULT hr = m_pServices->GetObject(_bstr_t(instancePath.c_str()),
0, NULL, &pInstance, NULL);
if (SUCCEEDED(hr)) {
hr = pInstance->Put(_bstr_t(propertyName.c_str()), 0, &value, 0);
if (SUCCEEDED(hr)) {
hr = m_pServices->PutInstance(pInstance,
WBEM_FLAG_UPDATE_ONLY,
NULL, NULL);
}
pInstance->Release();
}
return hr;
}
// Execute WMI method
HRESULT ExecuteMethod(const std::wstring& objectPath,
const std::wstring& methodName,
const std::map<std::wstring, _variant_t>& parameters = {},
std::map<std::wstring, _variant_t>* outParameters = nullptr) {
if (!m_initialized) {
return E_FAIL;
}
IWbemClassObject* pClass = nullptr;
IWbemClassObject* pInParamsDefinition = nullptr;
IWbemClassObject* pClassInstance = nullptr;
IWbemClassObject* pOutParams = nullptr;
HRESULT hr = m_pServices->GetObject(_bstr_t(objectPath.c_str()),
0, NULL, &pClass, NULL);
if (SUCCEEDED(hr)) {
hr = pClass->GetMethod(_bstr_t(methodName.c_str()), 0,
&pInParamsDefinition, NULL);
}
if (SUCCEEDED(hr) && pInParamsDefinition) {
hr = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
// Set input parameters
for (const auto& param : parameters) {
if (SUCCEEDED(hr)) {
hr = pClassInstance->Put(_bstr_t(param.first.c_str()),
0, &param.second, 0);
}
}
}
if (SUCCEEDED(hr)) {
hr = m_pServices->ExecMethod(_bstr_t(objectPath.c_str()),
_bstr_t(methodName.c_str()),
0, NULL, pClassInstance, &pOutParams, NULL);
}
// Get output parameters
if (SUCCEEDED(hr) && pOutParams && outParameters) {
hr = pOutParams->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
if (SUCCEEDED(hr)) {
BSTR propertyName = nullptr;
VARIANT propertyValue;
CIMTYPE propertyType;
LONG flavor;
while (pOutParams->Next(0, &propertyName, &propertyValue,
&propertyType, &flavor) == WBEM_S_NO_ERROR) {
(*outParameters)[std::wstring(propertyName)] = _variant_t(propertyValue);
SysFreeString(propertyName);
VariantClear(&propertyValue);
}
pOutParams->EndEnumeration();
}
}
// Cleanup
if (pClass) pClass->Release();
if (pInParamsDefinition) pInParamsDefinition->Release();
if (pClassInstance) pClassInstance->Release();
if (pOutParams) pOutParams->Release();
return hr;
}
// Monitor WMI events
HRESULT MonitorEvents(const std::wstring& query,
std::function<void(const std::map<std::wstring, _variant_t>&)> callback,
DWORD timeoutMs = INFINITE) {
if (!m_initialized) {
return E_FAIL;
}
IUnsecuredApartment* pUnsecApp = nullptr;
IWbemObjectSink* pSink = nullptr;
IWbemObjectSink* pStubSink = nullptr;
// Create event sink
class EventSink : public IWbemObjectSink {
private:
LONG m_refCount;
std::function<void(const std::map<std::wstring, _variant_t>&)> m_callback;
public:
EventSink(std::function<void(const std::map<std::wstring, _variant_t>&)> callback)
: m_refCount(0), m_callback(callback) {}
virtual ULONG STDMETHODCALLTYPE AddRef() {
return InterlockedIncrement(&m_refCount);
}
virtual ULONG STDMETHODCALLTYPE Release() {
LONG lRef = InterlockedDecrement(&m_refCount);
if (lRef == 0) delete this;
return lRef;
}
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) {
if (riid == IID_IUnknown || riid == IID_IWbemObjectSink) {
*ppv = (IWbemObjectSink*)this;
AddRef();
return WBEM_S_NO_ERROR;
}
return E_NOINTERFACE;
}
virtual HRESULT STDMETHODCALLTYPE Indicate(long lObjectCount,
IWbemClassObject __RPC_FAR* __RPC_FAR* apObjArray) {
for (int i = 0; i < lObjectCount; i++) {
std::map<std::wstring, _variant_t> eventData;
HRESULT hr = apObjArray[i]->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
if (SUCCEEDED(hr)) {
BSTR propertyName = nullptr;
VARIANT propertyValue;
CIMTYPE propertyType;
LONG flavor;
while (apObjArray[i]->Next(0, &propertyName, &propertyValue,
&propertyType, &flavor) == WBEM_S_NO_ERROR) {
eventData[std::wstring(propertyName)] = _variant_t(propertyValue);
SysFreeString(propertyName);
VariantClear(&propertyValue);
}
apObjArray[i]->EndEnumeration();
m_callback(eventData);
}
}
return WBEM_S_NO_ERROR;
}
virtual HRESULT STDMETHODCALLTYPE SetStatus(LONG lFlags, HRESULT hResult,
BSTR strParam, IWbemClassObject __RPC_FAR* pObjParam) {
return WBEM_S_NO_ERROR;
}
};
pSink = new EventSink(callback);
pSink->AddRef();
HRESULT hr = m_pServices->ExecNotificationQueryAsync(
_bstr_t(L"WQL"), _bstr_t(query.c_str()),
WBEM_FLAG_SEND_STATUS, NULL, pSink);
if (SUCCEEDED(hr)) {
// Wait for events
if (timeoutMs != INFINITE) {
Sleep(timeoutMs);
m_pServices->CancelAsyncCall(pSink);
}
}
if (pSink) pSink->Release();
return hr;
}
private:
void Cleanup() {
if (m_pServices) {
m_pServices->Release();
m_pServices = nullptr;
}
if (m_pLocator) {
m_pLocator->Release();
m_pLocator = nullptr;
}
if (m_initialized) {
CoUninitialize();
m_initialized = false;
}
}
};

2. System Information and Monitoring#

Comprehensive System Monitor#

// System Information Collection Framework
class SystemMonitor {
private:
WMIManager m_wmi;
public:
struct SystemInfo {
std::wstring computerName;
std::wstring operatingSystem;
std::wstring architecture;
std::wstring processor;
DWORD totalMemoryMB;
DWORD availableMemoryMB;
std::vector<std::wstring> networkAdapters;
std::vector<std::wstring> disks;
};
struct PerformanceCounters {
double cpuUsage;
double memoryUsage;
double diskUsage;
double networkUtilization;
DWORD processCount;
DWORD threadCount;
DWORD handleCount;
};
SystemMonitor() {}
// Initialize monitor
bool Initialize(const std::wstring& computerName = L".") {
return SUCCEEDED(m_wmi.Initialize(computerName));
}
// Get system information
SystemInfo GetSystemInformation() {
SystemInfo info = {};
try {
// Computer system information
auto computerResults = m_wmi.Query(L"SELECT * FROM Win32_ComputerSystem");
if (!computerResults.empty()) {
auto& computer = computerResults[0];
info.computerName = computer[L"Name"].bstrVal;
info.totalMemoryMB = static_cast<DWORD>(
_wtoi64(computer[L"TotalPhysicalMemory"].bstrVal) / (1024 * 1024));
}
// Operating system information
auto osResults = m_wmi.Query(L"SELECT * FROM Win32_OperatingSystem");
if (!osResults.empty()) {
auto& os = osResults[0];
info.operatingSystem = os[L"Caption"].bstrVal;
info.architecture = os[L"OSArchitecture"].bstrVal;
info.availableMemoryMB = static_cast<DWORD>(
_wtoi64(os[L"FreePhysicalMemory"].bstrVal) / 1024);
}
// Processor information
auto procResults = m_wmi.Query(L"SELECT Name FROM Win32_Processor");
if (!procResults.empty()) {
info.processor = procResults[0][L"Name"].bstrVal;
}
// Network adapters
auto netResults = m_wmi.Query(
L"SELECT Name FROM Win32_NetworkAdapter WHERE NetConnectionStatus = 2");
for (const auto& adapter : netResults) {
info.networkAdapters.push_back(adapter.at(L"Name").bstrVal);
}
// Disk drives
auto diskResults = m_wmi.Query(L"SELECT Caption FROM Win32_LogicalDisk");
for (const auto& disk : diskResults) {
info.disks.push_back(disk.at(L"Caption").bstrVal);
}
}
catch (const std::exception& e) {
std::wcerr << L"Error collecting system information: "
<< std::wstring(e.what(), e.what() + strlen(e.what())).c_str() << std::endl;
}
return info;
}
// Get performance counters
PerformanceCounters GetPerformanceCounters() {
PerformanceCounters counters = {};
try {
// CPU usage
auto cpuResults = m_wmi.Query(
L"SELECT LoadPercentage FROM Win32_Processor WHERE DeviceID='CPU0'");
if (!cpuResults.empty()) {
counters.cpuUsage = static_cast<double>(cpuResults[0][L"LoadPercentage"].uintVal);
}
// Memory usage
auto memResults = m_wmi.Query(
L"SELECT TotalVisibleMemorySize, FreePhysicalMemory FROM Win32_OperatingSystem");
if (!memResults.empty()) {
auto& mem = memResults[0];
DWORD total = mem[L"TotalVisibleMemorySize"].ulVal;
DWORD free = mem[L"FreePhysicalMemory"].ulVal;
counters.memoryUsage = ((double)(total - free) / total) * 100.0;
}
// Process count
auto procResults = m_wmi.Query(L"SELECT COUNT(*) AS ProcessCount FROM Win32_Process");
if (!procResults.empty()) {
counters.processCount = procResults[0][L"ProcessCount"].uintVal;
}
// Disk usage (C: drive)
auto diskResults = m_wmi.Query(
L"SELECT Size, FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='C:'");
if (!diskResults.empty()) {
auto& disk = diskResults[0];
ULONGLONG total = _wtoi64(disk[L"Size"].bstrVal);
ULONGLONG free = _wtoi64(disk[L"FreeSpace"].bstrVal);
counters.diskUsage = ((double)(total - free) / total) * 100.0;
}
}
catch (const std::exception& e) {
std::wcerr << L"Error collecting performance counters: "
<< std::wstring(e.what(), e.what() + strlen(e.what())).c_str() << std::endl;
}
return counters;
}
// Get running processes
std::vector<std::map<std::wstring, _variant_t>> GetRunningProcesses() {
return m_wmi.Query(
L"SELECT Name, ProcessId, WorkingSetSize, PageFileUsage, "
L"ThreadCount, HandleCount FROM Win32_Process");
}
// Get installed software
std::vector<std::map<std::wstring, _variant_t>> GetInstalledSoftware() {
return m_wmi.Query(
L"SELECT DisplayName, DisplayVersion, Publisher, InstallDate "
L"FROM Win32_Product");
}
// Get services status
std::vector<std::map<std::wstring, _variant_t>> GetServices() {
return m_wmi.Query(
L"SELECT Name, DisplayName, State, StartMode, StartName "
L"FROM Win32_Service");
}
// Get event logs
std::vector<std::map<std::wstring, _variant_t>> GetEventLogEntries(
const std::wstring& logName = L"System",
int maxEntries = 100) {
std::wstring query = L"SELECT TimeGenerated, EventCode, Type, SourceName, Message "
L"FROM Win32_NTLogEvent WHERE Logfile='" + logName + L"'";
auto results = m_wmi.Query(query);
// Sort by time and limit results
if (results.size() > static_cast<size_t>(maxEntries)) {
results.resize(maxEntries);
}
return results;
}
// Monitor file system changes
void MonitorFileSystemChanges(const std::wstring& path,
std::function<void(const std::wstring&, const std::wstring&)> callback) {
std::wstring query = L"SELECT * FROM __InstanceCreationEvent WITHIN 1 "
L"WHERE TargetInstance ISA 'CIM_DirectoryContainsFile' "
L"AND TargetInstance.GroupComponent='Win32_Directory.Name=\"" +
path + L"\"'";
m_wmi.MonitorEvents(query, [callback](const std::map<std::wstring, _variant_t>& eventData) {
try {
// Extract file information from event
auto targetInstance = eventData.at(L"TargetInstance");
// Process the event data
callback(L"FileCreated", L"New file detected");
}
catch (...) {
// Handle parsing errors
}
});
}
// Get hardware information
struct HardwareInfo {
std::wstring motherboard;
std::wstring bios;
std::vector<std::wstring> memory;
std::vector<std::wstring> storage;
std::wstring videoCard;
};
HardwareInfo GetHardwareInformation() {
HardwareInfo info = {};
try {
// Motherboard
auto mbResults = m_wmi.Query(
L"SELECT Product, Manufacturer FROM Win32_BaseBoard");
if (!mbResults.empty()) {
auto& mb = mbResults[0];
info.motherboard = mb[L"Manufacturer"].bstrVal +
std::wstring(L" ") + mb[L"Product"].bstrVal;
}
// BIOS
auto biosResults = m_wmi.Query(
L"SELECT Manufacturer, SMBIOSBIOSVersion FROM Win32_BIOS");
if (!biosResults.empty()) {
auto& bios = biosResults[0];
info.bios = bios[L"Manufacturer"].bstrVal +
std::wstring(L" ") + bios[L"SMBIOSBIOSVersion"].bstrVal;
}
// Memory
auto memResults = m_wmi.Query(
L"SELECT Capacity, Speed FROM Win32_PhysicalMemory");
for (const auto& mem : memResults) {
ULONGLONG capacity = _wtoi64(mem.at(L"Capacity").bstrVal);
DWORD capacityGB = static_cast<DWORD>(capacity / (1024 * 1024 * 1024));
DWORD speed = mem.at(L"Speed").uintVal;
std::wstring memInfo = std::to_wstring(capacityGB) + L"GB DDR" +
std::to_wstring(speed);
info.memory.push_back(memInfo);
}
// Storage devices
auto storageResults = m_wmi.Query(
L"SELECT Model, Size FROM Win32_DiskDrive");
for (const auto& storage : storageResults) {
std::wstring model = storage.at(L"Model").bstrVal;
ULONGLONG size = _wtoi64(storage.at(L"Size").bstrVal);
DWORD sizeGB = static_cast<DWORD>(size / (1024 * 1024 * 1024));
info.storage.push_back(model + L" (" + std::to_wstring(sizeGB) + L"GB)");
}
// Video card
auto videoResults = m_wmi.Query(
L"SELECT Name FROM Win32_VideoController WHERE Availability=3");
if (!videoResults.empty()) {
info.videoCard = videoResults[0][L"Name"].bstrVal;
}
}
catch (const std::exception& e) {
std::wcerr << L"Error collecting hardware information: "
<< std::wstring(e.what(), e.what() + strlen(e.what())).c_str() << std::endl;
}
return info;
}
};

3. PowerShell Integration#

PowerShell Host Implementation#

// PowerShell Host for C++ Applications
#include <msclr\marshal_cppstd.h>
#include <vcclr.h>
#using <System.dll>
#using <System.Management.Automation.dll>
using namespace System;
using namespace System::Management::Automation;
using namespace System::Management::Automation::Runspaces;
using namespace System::Collections::ObjectModel;
using namespace msclr::interop;
class PowerShellHost {
private:
Runspace^ m_runspace;
PowerShell^ m_powerShell;
public:
PowerShellHost() {
try {
// Create runspace
m_runspace = RunspaceFactory::CreateRunspace();
m_runspace->Open();
// Create PowerShell instance
m_powerShell = PowerShell::Create();
m_powerShell->Runspace = m_runspace;
}
catch (Exception^ ex) {
String^ error = ex->Message;
marshal_context ctx;
std::string errorMsg = ctx.marshal_as<std::string>(error);
throw std::runtime_error("Failed to initialize PowerShell: " + errorMsg);
}
}
~PowerShellHost() {
if (m_powerShell) {
delete m_powerShell;
}
if (m_runspace) {
m_runspace->Close();
delete m_runspace;
}
}
// Execute PowerShell command
std::vector<std::string> ExecuteCommand(const std::string& command) {
std::vector<std::string> results;
try {
String^ managedCommand = marshal_as<String^>(command);
m_powerShell->Commands->Clear();
m_powerShell->AddScript(managedCommand);
Collection<PSObject^>^ psResults = m_powerShell->Invoke();
for each(PSObject^ psObj in psResults) {
String^ result = psObj->ToString();
marshal_context ctx;
results.push_back(ctx.marshal_as<std::string>(result));
}
// Check for errors
if (m_powerShell->Streams->Error->Count > 0) {
for each(ErrorRecord^ error in m_powerShell->Streams->Error) {
String^ errorMsg = error->ToString();
marshal_context ctx;
throw std::runtime_error("PowerShell error: " +
ctx.marshal_as<std::string>(errorMsg));
}
}
}
catch (Exception^ ex) {
String^ error = ex->Message;
marshal_context ctx;
throw std::runtime_error("PowerShell execution failed: " +
ctx.marshal_as<std::string>(error));
}
return results;
}
// Execute script file
std::vector<std::string> ExecuteScriptFile(const std::string& scriptPath) {
std::string command = ". '" + scriptPath + "'";
return ExecuteCommand(command);
}
// Get system information via PowerShell
std::map<std::string, std::string> GetSystemInfo() {
std::map<std::string, std::string> info;
try {
// Computer information
auto computerInfo = ExecuteCommand("Get-ComputerInfo | ConvertTo-Json");
if (!computerInfo.empty()) {
// Parse JSON response (simplified)
info["ComputerName"] = "Retrieved via PowerShell";
}
// Process information
auto processInfo = ExecuteCommand(
"(Get-Process | Measure-Object).Count");
if (!processInfo.empty()) {
info["ProcessCount"] = processInfo[0];
}
// Service information
auto serviceInfo = ExecuteCommand(
"(Get-Service | Where-Object {$_.Status -eq 'Running'} | Measure-Object).Count");
if (!serviceInfo.empty()) {
info["RunningServices"] = serviceInfo[0];
}
}
catch (const std::exception& e) {
info["Error"] = e.what();
}
return info;
}
// Monitor Windows events
void MonitorWindowsEvents(const std::string& logName,
std::function<void(const std::string&)> callback) {
try {
std::string command =
"Register-WmiEvent -Query \"SELECT * FROM Win32_VolumeChangeEvent\" "
"-Action { Write-Host 'Drive change detected' }";
ExecuteCommand(command);
// In a real implementation, you'd set up event handling
callback("Event monitoring started for " + logName);
}
catch (const std::exception& e) {
callback("Error setting up event monitoring: " + std::string(e.what()));
}
}
};

4. Remote System Management#

WMI Remote Management Framework#

// Remote System Management Utilities
class RemoteSystemManager {
private:
std::vector<std::unique_ptr<WMIManager>> m_connections;
std::map<std::wstring, std::wstring> m_credentials;
public:
struct RemoteSystemInfo {
std::wstring computerName;
bool connected;
std::wstring lastError;
SystemMonitor::SystemInfo systemInfo;
SystemMonitor::PerformanceCounters performance;
};
// Add remote system
bool AddRemoteSystem(const std::wstring& computerName,
const std::wstring& userName = L"",
const std::wstring& password = L"") {
auto wmi = std::make_unique<WMIManager>();
HRESULT hr = wmi->Initialize(computerName, userName, password);
if (SUCCEEDED(hr)) {
m_connections.push_back(std::move(wmi));
if (!userName.empty()) {
m_credentials[computerName] = userName + L":" + password;
}
return true;
}
return false;
}
// Get information from all remote systems
std::vector<RemoteSystemInfo> GetAllSystemsInfo() {
std::vector<RemoteSystemInfo> systems;
for (size_t i = 0; i < m_connections.size(); ++i) {
RemoteSystemInfo info = {};
try {
SystemMonitor monitor;
// Note: This is simplified - you'd need to associate WMIManager with SystemMonitor
info.connected = true;
// info.systemInfo = monitor.GetSystemInformation();
// info.performance = monitor.GetPerformanceCounters();
}
catch (const std::exception& e) {
info.connected = false;
info.lastError = std::wstring(e.what(), e.what() + strlen(e.what()));
}
systems.push_back(info);
}
return systems;
}
// Execute remote command on all systems
std::map<std::wstring, std::vector<std::string>> ExecuteRemoteCommand(
const std::wstring& command) {
std::map<std::wstring, std::vector<std::string>> results;
for (size_t i = 0; i < m_connections.size(); ++i) {
try {
// Execute WMI-based command or PowerShell remotely
// This would require additional implementation
results[L"System_" + std::to_wstring(i)] = { "Command executed" };
}
catch (const std::exception& e) {
results[L"System_" + std::to_wstring(i)] = {
"Error: " + std::string(e.what())
};
}
}
return results;
}
// Deploy software remotely
bool DeploySoftware(const std::wstring& softwarePath,
const std::wstring& parameters = L"") {
bool allSucceeded = true;
for (auto& wmi : m_connections) {
try {
std::map<std::wstring, _variant_t> params;
params[L"CommandLine"] = _variant_t(softwarePath + L" " + parameters);
std::map<std::wstring, _variant_t> outParams;
HRESULT hr = wmi->ExecuteMethod(
L"Win32_Process", L"Create", params, &outParams);
if (FAILED(hr)) {
allSucceeded = false;
}
}
catch (const std::exception&) {
allSucceeded = false;
}
}
return allSucceeded;
}
// Collect logs from all systems
std::map<std::wstring, std::vector<std::map<std::wstring, _variant_t>>>
CollectEventLogs(const std::wstring& logName = L"System", int maxEntries = 50) {
std::map<std::wstring, std::vector<std::map<std::wstring, _variant_t>>> allLogs;
for (size_t i = 0; i < m_connections.size(); ++i) {
try {
SystemMonitor monitor;
// Associate with WMI connection
auto logs = monitor.GetEventLogEntries(logName, maxEntries);
allLogs[L"System_" + std::to_wstring(i)] = logs;
}
catch (const std::exception&) {
allLogs[L"System_" + std::to_wstring(i)] = {};
}
}
return allLogs;
}
};

5. Advanced WMI Features#

Custom WMI Provider#

// Custom WMI Provider Implementation
#include <wbemprov.h>
class CustomWMIProvider : public IWbemServices, public IWbemProviderInit {
private:
LONG m_refCount;
IWbemServices* m_namespace;
IWbemClassObject* m_class;
public:
CustomWMIProvider() : m_refCount(0), m_namespace(nullptr), m_class(nullptr) {}
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) {
if (riid == IID_IUnknown || riid == IID_IWbemServices) {
*ppv = static_cast<IWbemServices*>(this);
AddRef();
return S_OK;
}
if (riid == IID_IWbemProviderInit) {
*ppv = static_cast<IWbemProviderInit*>(this);
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) AddRef() {
return InterlockedIncrement(&m_refCount);
}
STDMETHODIMP_(ULONG) Release() {
LONG count = InterlockedDecrement(&m_refCount);
if (count == 0) delete this;
return count;
}
// IWbemProviderInit
STDMETHODIMP Initialize(
LPWSTR pszUser, LONG lFlags, LPWSTR pszNamespace, LPWSTR pszLocale,
IWbemServices* pNamespace, IWbemContext* pCtx, IWbemProviderInitSink* pInitSink) {
m_namespace = pNamespace;
if (m_namespace) m_namespace->AddRef();
pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
return WBEM_S_NO_ERROR;
}
// IWbemServices methods (implement required ones)
STDMETHODIMP CreateInstanceEnum(
const BSTR strClass, long lFlags, IWbemContext* pCtx,
IEnumWbemClassObject** ppEnum) {
// Create custom instances based on your application data
return WBEM_E_NOT_SUPPORTED;
}
STDMETHODIMP GetObject(
const BSTR strObjectPath, long lFlags, IWbemContext* pCtx,
IWbemClassObject** ppObject, IWbemCallResult** ppCallResult) {
// Return specific object instance
return WBEM_E_NOT_SUPPORTED;
}
STDMETHODIMP ExecQuery(
const BSTR strQueryLanguage, const BSTR strQuery, long lFlags,
IWbemContext* pCtx, IEnumWbemClassObject** ppEnum) {
// Process WQL queries
return WBEM_E_NOT_SUPPORTED;
}
// Implement other required IWbemServices methods with WBEM_E_NOT_SUPPORTED
STDMETHODIMP OpenNamespace(const BSTR strNamespace, long lFlags, IWbemContext* pCtx, IWbemServices** ppWorkingNamespace, IWbemCallResult** ppResult) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP CancelAsyncCall(IWbemObjectSink* pSink) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP QueryObjectSink(long lFlags, IWbemObjectSink** ppResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP GetObjectAsync(const BSTR strObjectPath, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP PutClass(IWbemClassObject* pObject, long lFlags, IWbemContext* pCtx, IWbemCallResult** ppCallResult) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP PutClassAsync(IWbemClassObject* pObject, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP DeleteClass(const BSTR strClass, long lFlags, IWbemContext* pCtx, IWbemCallResult** ppCallResult) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP DeleteClassAsync(const BSTR strClass, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP CreateClassEnum(const BSTR strSuperclass, long lFlags, IWbemContext* pCtx, IEnumWbemClassObject** ppEnum) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP CreateClassEnumAsync(const BSTR strSuperclass, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP PutInstance(IWbemClassObject* pInst, long lFlags, IWbemContext* pCtx, IWbemCallResult** ppCallResult) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP PutInstanceAsync(IWbemClassObject* pInst, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP DeleteInstance(const BSTR strObjectPath, long lFlags, IWbemContext* pCtx, IWbemCallResult** ppCallResult) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP DeleteInstanceAsync(const BSTR strObjectPath, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP CreateInstanceEnumAsync(const BSTR strClass, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP ExecQueryAsync(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP ExecNotificationQuery(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext* pCtx, IEnumWbemClassObject** ppEnum) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP ExecNotificationQueryAsync(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP ExecMethod(const BSTR strObjectPath, const BSTR strMethodName, long lFlags, IWbemContext* pCtx, IWbemClassObject* pInParams, IWbemClassObject** ppOutParams, IWbemCallResult** ppCallResult) { return WBEM_E_NOT_SUPPORTED; }
STDMETHODIMP ExecMethodAsync(const BSTR strObjectPath, const BSTR strMethodName, long lFlags, IWbemContext* pCtx, IWbemClassObject* pInParams, IWbemObjectSink* pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
};

Best Practices#

1. Error Handling#

  • Always check HRESULT return values
  • Implement proper COM cleanup
  • Use exception handling for WMI operations
  • Log errors appropriately

2. Security Considerations#

// Secure WMI connections
HRESULT SecureWMIConnection(IWbemServices* pServices) {
return CoSetProxyBlanket(
pServices,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
}

3. Performance Optimization#

  • Use asynchronous operations for long-running queries
  • Implement connection pooling for multiple systems
  • Cache frequently accessed data
  • Use appropriate query filters

4. Memory Management#

  • Properly release COM interfaces
  • Use RAII patterns for automatic cleanup
  • Handle BSTR allocations correctly
  • Monitor memory usage in long-running applications

Conclusion#

WMI and system management programming provides powerful capabilities for Windows administration and monitoring. This guide covers essential techniques from basic WMI operations to advanced remote management and custom providers.

Key takeaways:

  • WMI Framework: Comprehensive system management interface
  • Remote Management: Enterprise-scale system administration
  • PowerShell Integration: Modern scripting capabilities
  • Performance Monitoring: Real-time system metrics
  • Custom Providers: Extending WMI functionality

Master these system management techniques to build robust Windows administration tools and enterprise management solutions.

Windows WMI & System Management: Complete Administrator's Guide
https://mranv.pages.dev/posts/2025/windows-wmi-system-management/
Author
Anubhav Gain
Published at
2025-08-17
License
CC BY-NC-SA 4.0