代码之家  ›  专栏  ›  技术社区  ›  CrazyCoder

如何在COM中获取executbale的安装应用程序路径

  •  3
  • CrazyCoder  · 技术社区  · 7 年前

    我正在尝试使用COM获取所有应用程序的安装位置。我能够获得每个应用程序的显示名称。但我无法获得每个应用程序的安装路径。

    我的代码:

    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获取安装路径吗。

    谢谢你的支持。

    1 回复  |  直到 7 年前
        1
  •  3
  •   Simon Mourier    7 年前

    下面是一段代码,可以将其转储。孩子的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:我没有添加太多的错误检查,但你应该。