A customer wanted to be able to get the target of a shortcut
with environment variables unexpanded.
The IShellLink::GetPath
method
will expand environment variables.
The way to get the unexpanded target path is to go for the
EXP_SZ_LINK
data in the shell link data list.
We
briefly encountered the shell link data list a while back.
Now we’ll dig in a little more.
#include <windows.h> #include <shlobj.h> #include <stdio.h> // Horrors! Mixing stdio and C++! #include <atlbase.h> #include <atlalloc.h> int __cdecl wmain(int argc, wchar_t**argv) { CCoInitialize init; CComPtr<IShellLink> lnk; CoCreateInstance(CLSID_ShellLink, 0, CLSCTX_ALL, IID_PPV_ARGS(&lnk)); CComQIPtr<IPersistFile> pf(lnk); pf->Load(argv[1], STGM_READ); CComQIPtr<IShellLinkDataList> list(lnk); DWORD flags; list->GetFlags(&flags); if (flags & SLDF_HAS_EXP_SZ) { CHeapPtr<void, CLocalAllocator> rawData; list->CopyDataBlock(EXP_SZ_LINK_SIG, &rawData); auto linkData = reinterpret_cast<EXP_SZ_LINK *>(static_cast<void *>(rawData)); printf("Unexpanded target = %ls\n", linkData->swzTarget); } return 0; }
After loading the shortcut file,
we ask the
IShellLinkDataList
to inspect the
shortcut flags.
If the SLDF_HAS_EXP_SZ
flag is set,
then the path to the target contains an environment variable reference.
To get the original unexpanded path, ask for the
EXP_SZ_LINK_SIG
data block.
That returns a data block in the form of a
EXP_SZ_LINK
structure,
from which you can extract the unexpanded paths.