List installed programs (Windows)
The only way I know is via WMI but it's relatively complicated because it uses COM model. It has one advantage - once you set it up you can query a lot of useful info from system.
I can post some code if you want.
I can post some code if you want.
You could look in the registry. Usually applications put a key into HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall when they are installed.
So as you asked, here is some basic code to get WMI up and detect all installed applications.
The biggest part of this code is just to provide nicer interface to VARIANTS which store values of properties in WMI objects.
Actual detection of installed applications happens in the line which contains
There you query WMI for all objects of type Win32_Product. This classes store info about installed applications.
For more info about properties of such class look into MSDN documentation.
NOTE: I have tested this application and it works nicely. However there can be stupid errors in VariantToString() function as I can't test all possible VARIANTS.
#define _WIN32_DCOM#include <comdef.h>#include <Wbemidl.h>#include <string>#include <iostream>#include <sstream>using namespace std;// this library is required#pragma comment(lib, "wbemuuid.lib")/* Forward declarations */string DoubleToString(double d);string VariantToString(const VARIANT &var);string GetPropertyAsString(LPCWSTR name, IWbemClassObject *Object);int main(void){ HRESULT hres; // Initialize COM. hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl; return 1; } // Set general COM security levels hres = CoInitializeSecurity(NULL, // Security descriptor -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 2; } // Obtain the initial locator to WMI IWbemLocator *Locator = NULL; hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &Locator); if (FAILED(hres)) { cout << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << endl; CoUninitialize(); return 3; } // Connect to WMI through the IWbemLocator::ConnectServer method IWbemServices *Services = NULL; // Connect to the root\cimv2 namespace, this namespace contains all we want hres = Locator->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), // Connect to CIMV2 namespace of WMI NULL, // User Name (NULL = curren user) NULL, // User Password (NULL = current) 0, // Locale, current NULL, // Security flags 0, // Authority 0, // Context object &Services); // IWbemServices proxy if (FAILED(hres)) { cout << "Could not connect. Error code = 0x" << hex << hres << endl; Locator->Release(); CoUninitialize(); return 4; } cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl; // Set security levels on the proxy hres = CoSetProxyBlanket(Services, // 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; Services->Release(); Locator->Release(); CoUninitialize(); return 5; } // Enumerator is used to enumerate CIM objects IEnumWbemClassObject *Enumerator = NULL; // Crate enumerator which contains all installed products // Queries are specified in language similar to SQL // Here we select all objects with class Win32_Product (this class represents installed application) hres = Services->ExecQuery(bstr_t("WQL"), // Query language, must be WQL bstr_t("SELECT * FROM Win32_Product"), // Query WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &Enumerator); if (FAILED(hres)) { cout << "Query for enumerator failed." << " Error code = 0x" << hex << hres << endl; Services->Release(); Locator->Release(); CoUninitialize(); return 6; } HRESULT hRes = WBEM_S_NO_ERROR; // while we have something in enumeration while (hRes == WBEM_S_NO_ERROR) { const int object_count = 1; // number of objects to return ULONG returned = 0; // number of objects actually returned IWbemClassObject *ClassObjects[object_count] = {NULL}; // space to hold returned objects // get next object_count objects from enumerator hRes = Enumerator->Next(WBEM_INFINITE, object_count, ClassObjects, &returned); // no error if (SUCCEEDED(hRes)) { // for each returned object output its properties to screen for (unsigned int i = 0; i < returned; i++) { // Output some of the properties cout << "Name: " << GetPropertyAsString(L"Name", ClassObjects) << endl; cout << "Vendor: " << GetPropertyAsString(L"Vendor", ClassObjects) << endl; cout << "Version: " << GetPropertyAsString(L"Version", ClassObjects) << endl; cout << "********" << endl; ClassObjects->Release(); } } } // Cleanup Services->Release(); Locator->Release(); Enumerator->Release(); CoUninitialize(); getchar(); return 0;}/* Convert double to string */string DoubleToString(double d) { stringstream str; str << d; return str.str();}/* Convert value stored in VARIANT to string for easier manipulation */string VariantToString(const VARIANT &var) { char buffer[40] = {0}; // Temp buffer for numbers switch (var.vt) { default: case VT_NULL: // no value case VT_EMPTY: // no value case VT_EMPTY | VT_BYREF: // bad variant return string("unknown"); case VT_UI1: // char _ultoa((long) var.bVal, buffer, 10); break; case VT_UI1 | VT_BYREF: // Reference to char _ultoa((long) *var.pbVal, buffer, 10); break; case VT_UI2: // 16 bit unsigned int _ultoa((long) var.uiVal, buffer, 10); break; case VT_UI2 | VT_BYREF: // Reference to 16 bit unsigned int _ultoa((long) *var.puiVal, buffer, 10); break; case VT_UI4: // 32 bit unsigned int _ultoa((long) var.ulVal, buffer, 10); break; case VT_UI4 | VT_BYREF: // Reference to 32 bit unsigned int _ultoa((long) *var.pulVal, buffer, 10); break; case VT_UI8: // 64 bit unsigned int _ui64toa((unsigned __int64) var.ullVal, buffer, 10); break; case VT_UI8 | VT_BYREF: // Reference to 64 bit unsigned int _ui64toa((unsigned __int64) *var.pullVal, buffer, 10); break; case VT_UINT: // Unsigned int _ultoa((long) var.uintVal, buffer, 10); break; case VT_UINT | VT_BYREF: // Reference to unsigned int _ultoa((long) *var.puintVal, buffer, 10); break; case VT_INT: // int _ltoa((long) var.intVal, buffer, 10); break; case VT_INT | VT_BYREF: // Reference to int _ltoa((long) *var.puintVal, buffer, 10); break; case VT_I1: // char _ltoa((long) var.cVal, buffer, 10); break; case VT_I1 | VT_BYREF: // reference to char _ltoa((long) *var.pcVal, buffer, 10); break; case VT_I2: // 16 bit int _ltoa((long) var.iVal, buffer, 10); break; case VT_I2 | VT_BYREF: // Pointer to 16 bit int _ltoa((long) *var.piVal, buffer, 10); break; case VT_I4: // 32 bit int _ltoa((long) var.lVal, buffer, 10); break; case VT_I4 | VT_BYREF: // Pointer to 32 bit int _ltoa((long) *var.plVal, buffer, 10); break; case VT_I8: // 64 bit int _i64toa((__int64) var.llVal, buffer, 10); break; case VT_I8 | VT_BYREF: // Pointer to 64 bit int _i64toa((__int64) *var.pllVal, buffer, 10); break; case VT_R4: // 32 bit real (float) return DoubleToString((double) var.fltVal); case VT_R4 | VT_BYREF: // Pointer to 32 bit real (float) return DoubleToString((double) *var.pfltVal); case VT_R8: // double return DoubleToString(var.dblVal); case VT_R8 | VT_BYREF: // Pointer to double return DoubleToString(*var.pdblVal); case VT_BSTR: // string (BSTR) { char str[1024] = ""; WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, str, 1024, NULL, NULL); return string(str); } case VT_BSTR | VT_BYREF: // Pointer to string (BSTR) { char str[1024] = ""; WideCharToMultiByte(CP_ACP, 0, *var.pbstrVal, -1, str, 1024, NULL, NULL); return string(str); } case VT_BOOL: // BOOL if (var.boolVal == 0) { strcpy(buffer, "false"); } else { strcpy(buffer, "true"); } break; case VT_BOOL | VT_BYREF: // Pointer to BOOL if (*var.pboolVal == 0) { strcpy(buffer, "false"); } else { strcpy(buffer, "true"); } break; } return string(buffer);}/* Get value of property named name from given object and convert it to std::string */string GetPropertyAsString(LPCWSTR name, IWbemClassObject *Object){ string result; VARIANT Value; // error, return empty string if (Object == NULL) return string(""); // initialize variant to empty one VariantInit(&Value); // get value of property Object->Get(name, 0, &Value, 0, 0); // convert it to string result = VariantToString(Value); // free memory used by variant VariantClear(&Value); return result;}
The biggest part of this code is just to provide nicer interface to VARIANTS which store values of properties in WMI objects.
Actual detection of installed applications happens in the line which contains
Services->ExecQuery(...)
There you query WMI for all objects of type Win32_Product. This classes store info about installed applications.
For more info about properties of such class look into MSDN documentation.
NOTE: I have tested this application and it works nicely. However there can be stupid errors in VariantToString() function as I can't test all possible VARIANTS.
For the ones who are interested, here's a MSDN link explaining the way to handle : Creating a WMI Application Using C++
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement