2017-11-27 18 views
3

COMを使用してすべてのアプリケーションのインストール先を取得しようとしています。私は各アプリケーションの表示名を得ることができます。しかし、私は各アプリケーションのインストールされたパスを取得することができません。COMでexecutbaleのインストールされたアプリケーションパスを取得する方法

MYコード:

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; 
} 

IEnumShellItemsからのパスをインストールし取得する方法任意のアイデア。

ありがとうございます。

+0

インストールされたパスでは、(オプションの)「Location」列を意味しますか? –

+0

はい;私は場所を取得したい。 – CrazyCoder

答えて

2

ここにこれを捨てるコードがあります。子供のIPropertyStoreはこれらを返さないので、理由はわからないので、古い IShellFolder2::GetDetailsEx methodを特別な列ID(これは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); 
    } 
} 

は、それが文書化されていないSystem.Software.InstallLocation PROPERTYKEYを使用しています。

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:それを見つけるために私はそれぞれの子のために、このようなコードですべての列をダンプ私はずっとエラーチェックを追加していませんでしたが、あなたはする必要があります。

+0

ありがとう@サイモン。 :)私はCoInitialize(NULL)を追加しました。それ以外の場合は、SHCreateItemFromParsingNameはNULLを返します。どのように私はエラーチェックを追加し、それは私のために正常に動作しています。再度、感謝します。 :) – CrazyCoder

+0

はい、ほとんどのシェル関数はCOMを初期化する必要があります。 –

+0

@CrazyCoder、賞金の有効期限が切れる前にこの回答を受け入れる必要があります –

関連する問題