Wednesday, December 6, 2017

How to get installed applicatio path for executbale in COM

Leave a Comment

I am trying to get installed location of all application using COM. I am able to get the display name of each application. But I am not able to get installed path of each application.

MY Code:

CComPtr<IShellItem> spPrinters;         CoInitialize(nullptr);         HRESULT hresult = ::SHCreateItemFromParsingName(L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\8\\"             L"::{7B81BE6A-CE2B-4676-A29E-EB907A5126C5}", nullptr, IID_PPV_ARGS(&spPrinters));         CComPtr<IEnumShellItems> spEnum;         spPrinters->BindToHandler(nullptr, BHID_EnumItems, IID_PPV_ARGS(&spEnum));         for (CComPtr<IShellItem> spProgram; spEnum->Next(1, &spProgram, nullptr) == S_OK; spProgram.Release())         {             CComHeapPtr<wchar_t> spszName;             spProgram->GetDisplayName(SIGDN_NORMALDISPLAY, &spszName);             CString cDisplayName = spszName; } 

Any idea how to get installed path from IEnumShellItems.

Thanks in adv.

1 Answers

Answers 1

Here is a piece of code that will dump this out. The child's IPropertyStore does not return these, I don't know why, so we have to use the old IShellFolder2::GetDetailsEx method with a special column id (which is the same as a PROPERTYKEY).

CComPtr<IShellItem> cpl; CComPtr<IShellFolder2> folder; CComPtr<IEnumShellItems> enumerator; PROPERTYKEY pkLocation; SHCreateItemFromParsingName(L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\8\\::{7B81BE6A-CE2B-4676-A29E-EB907A5126C5}", nullptr, IID_PPV_ARGS(&cpl));  // bind to IShellFolder cpl->BindToHandler(NULL, BHID_SFObject, IID_PPV_ARGS(&folder));  // bind to IEnumShellItems cpl->BindToHandler(NULL, BHID_EnumItems, IID_PPV_ARGS(&enumerator));  // get this property key's value PSGetPropertyKeyFromName(L"System.Software.InstallLocation", &pkLocation);  for (CComPtr<IShellItem> child; enumerator->Next(1, &child, nullptr) == S_OK; child.Release()) {     // get child's display name     CComHeapPtr<wchar_t> name;     child->GetDisplayName(SIGDN_NORMALDISPLAY, &name);     wprintf(L"%s\n", name);      // get child's PIDL     CComHeapPtr<ITEMIDLIST> pidl;     SHGetIDListFromObject(child, &pidl);      // the PIDL is absolute, we need the relative one (the last itemId in the list)     // get it's install location     CComVariant v;     if (SUCCEEDED(folder->GetDetailsEx(ILFindLastID(pidl), &pkLocation, &v)))     {         // it's a VT_BSTR         wprintf(L" %s\n", v.bstrVal);     } } 

Note it's using an undocumented System.Software.InstallLocation PROPERTYKEY. To find it I just dumped all columns with a code like this for each child:

    int iCol = 0;     do     {         SHCOLUMNID colId;         if (FAILED(folder->MapColumnToSCID(iCol, &colId)))             break; // last column          CComHeapPtr<wchar_t> name;         PSGetNameFromPropertyKey(colId, &name);          CComVariant v;         if (SUCCEEDED(folder->GetDetailsEx(ILFindLastID(pidl), &colId, &v)))         {             if (v.vt == VT_BSTR)             {                 wprintf(L" %s: %s\n", name, v.bstrVal);             }             else             {                 wprintf(L" %s vt: %i\n", name, v.vt);             }         }          iCol++;     } while (true); } 

PS: I've not added much error checking, but you should.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment