IShellLinkW::GetPath( SLGP_RAWPATH ) 不 return lnk 文件的 'raw' 目标

IShellLinkW::GetPath( SLGP_RAWPATH ) does not return the 'raw' target of a lnk file

我注意到方法 IShellLinkW::GetPath returns 如果快捷方式的目标指向特殊文件夹,如 'My PC' 或控制面板小程序,则为空字符串。

示例代码

' CLSID_ShellLink from ShlGuid.h
Dim cShellLink As New CShellLink() 

' https://msdn.microsoft.com/en-us/library/windows/desktop/ms687223%28v=vs.85%29.aspx
Dim persistFile As IPersistFile = DirectCast(cShellLink, IPersistFile) 
persistFile.Load(lnkFilePath, 0)

Dim target As New StringBuilder(260)

' https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nn-shobjidl_core-ishelllinkw
Dim lnkW As IShellLinkW = DirectCast(cShellLink, IShellLinkW)
lnkW.GetPath(target, target.Capacity, Nothing, IShellLinkGetPathFlags.RawPath)

(抱歉,P/Invokes 太多,无法在此处分享,但您可以在 this 存储库中找到它们。)

上面的代码可以正确地检索任何指向文件或目录的 .lnk 文件的目标。它无法检索指向特殊项目/虚拟文件夹的目标。

我的问题是:

这是设计使然吗?如果没有,我错过了什么或做错了什么? (也许我的定义有误?)。为了检索特殊目标,我必须做什么?。请注意,我想检索目标以在 PropertyGrid 中显示它,并创建一个带有特殊目标克隆的新目标。

请注意,我开发此代码所用的编程语言无关紧要,因为我首先要求方向,并且我接受任何用 C# 编写的解决方案。

如主 post 的评论框中所述,为了检索指向特殊 shell link 的原始目标,non-file系统路径(例如 'My PC'),首先我们需要通过调用 IShellLinkW::GetIDList().

来检索 PIDL

接下来,我们将那个(绝对)PIDL 传递给 SHGetNameFromIDList with the flag SIGDN_DESKTOPABSOLUTEPARSING,最后这将 return 一个 CLSID 字符串,我们可以使用 [=11= 为 .lnk 文件的目标指定该字符串].它按预期工作。

请注意,我不确定是否存在无法按预期工作的特殊情况(lnk 文件的罕见目标)。我没有找到那个错误案例。

如果需要,可以使用标志 SIGDN_NORMALDISPLAY 获得正常的显示名称,或者也可以通过调用 SHGetFileInfo 函数来获得,正如主 post.


感谢向我推荐 PIDL 检索及其用法的用户,因为我不确定要调查什么才能解决这个问题。

我也会给 Vanara open-source library, that helped me to find the right P/Invokes of every SH* function in their source-code, specially the signature for SHGetNameFromIDList 点赞。