Get WMI Information in C# / Visual C++
I’ve received a couple of comments on the post about finding CPU and Motherboard Info through WMI for providing Visual C++ and VB.NET programs to get WMI information. I’m not a champ at Visual C++ and VB.NET (I usually work with PHP, its about 3 years ago when I worked with C++, C# and VB.NET), but I researched for some working solutions to get this task done for my readers.
I’ve been researching for a C# or C++ program to fetch WMI Information and came across several programs on web but none of them were in the working state, before I received a mail from M Dougann containing a working program for the task.
This article wraps in a working C# / Visual C++ program to get WMI Information, shared by M Dougann.
#define _WIN32_DCOM #pragma comment(lib, "wbemuuid.lib") #include <iostream> #include <string> #include <stdexcept> #include <stdlib.h> // EXIT_FAILURE, EXIT_SUCCESS using namespace std; #include lgt;comdef.h> #include <Wbemidl.h> #define DEF_SMARTPTR_TYPE( Interface ) _COM_SMARTPTR_TYPEDEF( Interface, __uuidof( Interface ) ) DEF_SMARTPTR_TYPE( IWbemLocator ); DEF_SMARTPTR_TYPE( IWbemServices ); DEF_SMARTPTR_TYPE( IWbemClassObject ); bool throwX( string const& s ) { throw std::runtime_error( s ); } string hexFrom( unsigned long v ) { char buf[40]; sprintf( buf, "%08lx", v ); return buf; } struct Fail { string message; explicit Fail( string const& aMessage ): message( aMessage ) {} }; void operator ||( HRESULT hr, Fail const& failure ) { SUCCEEDED( hr ) || throwX( failure.message + " (Error code 0x" + hexFrom( hr ) + ")" ); } struct ComLibUsage { struct Threading { enum Enum { singleThreaded = COINIT_APARTMENTTHREADED, multiThreaded = COINIT_MULTITHREADED }; }; ComLibUsage( Threading::Enum threading = Threading::multiThreaded ) { ::CoInitializeEx( 0, threading ) || Fail( "Failed to initialize COM library." ); } ~ComLibUsage() { ::CoUninitialize(); } }; void cppMain() { // Step 1: // Initialize COM. ComLibUsage comLibUsage( ComLibUsage::Threading::multiThreaded ); // Step 2: // Set general COM security levels // Note: If you are using Windows 2000, you must specify - // the default authentication credentials for a user by using // a SOLE_AUTHENTICATION_LIST structure in the pAuthList // parameter of CoInitializeSecurity CoInitializeSecurity( NULL, -1, // COM negotiates service 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 ) || Fail( "Failed to initialize security" ); // Step 3: // Obtain the initial locator to WMI IWbemLocatorPtr pLoc; CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc ) || Fail( "Failed to create IWbemLocator object." ); // Step 4: // Connect to WMI through the IWbemLocator::ConnectServer method // Connect to the local rootcimv2 namespace // and obtain pointer pSvc to make IWbemServices calls. IWbemServicesPtr pSvc; pLoc->ConnectServer( _bstr_t(L"ROOT\wmi"), NULL, NULL, 0, NULL, 0, 0, &pSvc ) || Fail( "Could not connect." ); cout << "Connected to ROOT\CIMV2 WMI namespace" << endl; // Step 5: // Set security levels for the proxy 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 ) || Fail( "Could not set proxy blanket" ); // set up to call the WmiSetBrightness Method _bstr_t methodName = L"WmiSetBrightness"; _bstr_t className = L"WmiMonitorBrightnessMethods"; IWbemClassObjectPtr pClass; pSvc->GetObject(className, 0, NULL, &pClass, NULL) || Fail( "GetObject(className, ...) failed" ); IWbemClassObjectPtr pInParamsDefinition; pClass->GetMethod(methodName, 0, &pInParamsDefinition, NULL) || Fail( "GetMethod(methodName, ...) failed" ); IWbemClassObjectPtr pClassInstance; pInParamsDefinition->SpawnInstance(0, &pClassInstance) || Fail( "SpawnInstance failed" ); _variant_t var1( L"1000" ); pClassInstance->Put(L"Timeout", 0, &var1, CIM_UINT32) //CIM_UINT64 || Fail( "Put failed for 'Timeout'" ); _variant_t var2( L"30" ); pClassInstance->Put(L"Brightness", 0, &var2, CIM_UINT8) || Fail( "Put failed for 'Brightness'" ); // Execute Method IWbemClassObject* pOutParams = NULL; //hres = pSvc->ExecMethod(className, methodName, 0, //NULL, pClassInstance, &pOutParams, NULL) //|| Fail( "Could not execute method" ); // To see what the method returned, // use the following code. The return value will // be in &varReturnValue _variant_t varReturnValue; pOutParams->Get(_bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0) || Fail( "Get failed" ); } int main() { try { cppMain(); return EXIT_SUCCESS; } catch( exception const& x ) { cerr << "!" << x.what() << endl; } return EXIT_FAILURE; }
I hope this article has helped you to obtain WMI Information through C# / C++, feel free to post your queries, I’ll try my best to provide the solutions and fixes.