While trying to implement "Open With" functionality I encountered a problem with extracting icons from UWP applications. So, after receiving list of recommended applications to open particular file with the help of SHAssocEnumHandlers, I'm trying to extract icons for each of these applications with the help of IAssocHandler::GetIconLocation and classical ExtractIcon()
. Everything works ok with programs like Paint, for example. I have full path to Paint binary and can extract icon from it. But with applications like "3D builder", "Photos" and other UWP applications obtained icon location looks like @{Microsoft.Windows.Photos_16.511.8630.0_x64__8wekyb3d8bbwe?ms-resource://Microsoft.Windows.Photos/Files/Assets/PhotosAppList.png}
. I tried couple of different APIs to extract icon and each time received FILE_NOT_FOUND error. So, can anyone give me a hint which function can be used to extract icon in that case?
UPDATE Some parts of source code added to clarify the situation:
// m_handlers is a member of type std::vector<CComPtr<IAssocHandler>>
HRESULT FileManager::GetAssocHandlers(const std::wstring& strFileExtension, ASSOC_FILTER filter)
{
HRESULT hr = S_OK;
CComPtr<IEnumAssocHandlers> enumerator;
m_handlers.clear();
hr = SHAssocEnumHandlers(strFileExtension.c_str(), filter, &enumerator);
if (SUCCEEDED(hr))
{
for (CComPtr<IAssocHandler> handler;
enumerator->Next(1, &handler, nullptr) == S_OK;
handler.Release())
{
m_handlers.push_back(handler);
}
}
return hr;
}
HRESULT FileManager::GetAssociatedPrograms(BSTR bstrFileName, BSTR* bstrRet)
{
...
hr = GetAssocHandlers(strFileExtension, ASSOC_FILTER_RECOMMENDED);
if (SUCCEEDED(hr))
{
...
for (auto& handler : m_handlers)
{
...
if (SUCCEEDED(handler->GetIconLocation(&tmpStr, &resourceIndex)))
{
// And this is where I get classic full file path to regular
// applications like "MS Paint" or this weird path mentioned
// above for "Photos" UWP application for example which can't
// be used in regular ExtractIcon functions.
}
}
}
}
Looks like I've found the solution. The icon location path provided for UWP application is called "indirect string" according to MSDN. We can pass this indirect string to SHLoadIndirectString function and will receive the regular full path to the icon PNG file. In my case after passing
@{Microsoft.Windows.Photos_16.511.8630.0_x64__8wekyb3d8bbwe?ms-resource://Microsoft.Windows.Photos/Files/Assets/PhotosAppList.png}
to SHLoadIndirectString() I received path like that:C:\Program Files\WindowsApps\Microsoft.Windows.Photos_16.511.8630.0_neutral_split.scale-125_8wekyb3d8bbwe\Assets\PhotosAppList.scale-125.png
and after that I can use it to display the icon itself w/o any problem.