Reputation:
I have a path of the form
::{26EE0668-A00A-44D7-9371-BEB064C98683}\0\Fonts
If I enter this into the explorer address bar it correctly opens Control Panel - Fonts.
How can I execute the same using ShellExecuteEx or something similar (a path containing guids)?
Upvotes: 2
Views: 461
Reputation: 27786
To open such GUID pathes you have to prepend the shell:
protocol to the path:
shell:::{26EE0668-A00A-44D7-9371-BEB064C98683}\0\Fonts
Note that GUID pathes often change between Windows versions, for instance the above path doesn't work on my Windows 10 machine.
A better approach is to use the known folder API to get a PIDL that points to the folder and open that PIDL using ShellExecuteEx
:
#include <iostream>
#include <windows.h>
#include <shellapi.h>
#include <atlbase.h> // CComHeapPtr
struct CComInit
{
HRESULT hr = E_FAIL;
CComInit() { hr = ::CoInitialize(nullptr); }
~CComInit() { if( SUCCEEDED(hr) ) ::CoUninitialize(); }
};
int main()
{
CComInit com;
if( FAILED( com.hr ) )
{
std::cout << "Failed to initialize COM, error: 0x" << std::hex << com.hr << '\n';
return static_cast<int>( com.hr );
}
CComHeapPtr<ITEMIDLIST> pidl;
HRESULT hr = ::SHGetKnownFolderIDList( FOLDERID_Fonts, KF_FLAG_DEFAULT, nullptr, &pidl );
if( FAILED( hr ) )
{
std::cout << "SHGetKnownFolderIDList failed with error 0x" << std::hex << hr << '\n';
return static_cast<int>( hr );
}
SHELLEXECUTEINFOW si{ sizeof(si) };
si.fMask = SEE_MASK_NOASYNC | SEE_MASK_IDLIST;
si.nShow = SW_SHOWDEFAULT;
si.lpVerb = L"open";
si.lpIDList = pidl;
if( !::ShellExecuteExW( &si ) )
{
DWORD err = ::GetLastError();
std::cout << "ShellExecuteExW failed with error " << err << '\n';
return static_cast<int>( err );
}
return 0;
}
Notes:
CComHeapPtr
is a smart pointer that automatically calls CoTaskMemFree()
in its destructor to correctly deallocate the PIDL that was allocated by the shell. If you don't want to use it, you have to call CoTaskMemFree()
manually or use your own RAII wrapper to do this.SEE_MASK_NOASYNC
is used because the example is a console program that will exit immediately after the ShellExecuteEx
call.Upvotes: 3