Sign in to follow this  
iliak

List installed programs (Windows)

Recommended Posts

b2b3    602
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.

Share this post


Link to post
Share on other sites
IndyJones    298
You could look in the registry. Usually applications put a key into HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall when they are installed.

Share this post


Link to post
Share on other sites
b2b3    602
So as you asked, here is some basic code to get WMI up and detect all installed applications.


#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[i]) << endl;
cout << "Vendor: " << GetPropertyAsString(L"Vendor", ClassObjects[i]) << endl;
cout << "Version: " << GetPropertyAsString(L"Version", ClassObjects[i]) << endl;
cout << "********" << endl;
ClassObjects[i]->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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this