user2233208
user2233208

Reputation:

ShellExecuteEx guid path

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

Answers (1)

zett42
zett42

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:

  • The ATL class 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.
  • The flag SEE_MASK_NOASYNC is used because the example is a console program that will exit immediately after the ShellExecuteEx call.

Upvotes: 3

Related Questions