IShellLinkW :: GetPath(SLGP_RAWPATH)不返回lnk文件的“原始”目标

时间:2019-05-27 20:40:09

标签: c# .net vb.net lnk

我注意到,如果快捷方式的目标指向特殊文件夹(例如“我的电脑”或“控制面板”小程序),则方法IShellLinkW::GetPath将返回一个空字符串。

示例代码

' 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#编写的解决方案。

1 个答案:

答案 0 :(得分:1)

如主要文章的评论框中所述,为了检索指向特殊的非文件系统路径(例如“我的电脑”)的shell链接的原始目标,首先,我们需要检索通过调用IShellLinkW::GetIDList()来建立PIDL。

接下来,我们将(绝对)PIDL与标志SHGetNameFromIDList传递给SIGDN_DESKTOPABSOLUTEPARSING,最后这将返回一个CLSID字符串,我们可以使用{{ 1}}。它按预期工作。

请注意,我不确定是否会存在某些特殊情况(lnk文件的罕见目标),在这些特殊情况下无法按预期工作。我没有发现这种错误情况。

如果需要,可以使用标志IShellLinkW::SetPath()或通过调用SHGetFileInfo函数(如主帖子的注释框中所述)获得常规显示名称。


为那些向我建议PIDL检索及其用途的用户提供了信用,因为我不确定要解决什么问题才能进行调查。

我还将感谢Vanara开源库,它帮助我在其源代码中特别是the signature for SHGetNameFromIDList的每个SH *函数中找到了正确的P /调用。