2

我注意到,如果快捷方式的目标指向特殊文件夹(如“我的电脑”或控制面板小程序) ,则方法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 太多,但您可以在存储库中找到它们。)

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

我的问题是:

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

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

4

1 回答 1

2

如主帖的评论框中所述,为了检索指向特殊的非文件系统路径(例如“我的 PC”)的 shell 链接的原始目标,首先我们需要通过以下方式检索 PIDL打电话IShellLinkW::GetIDList()

接下来,我们将(绝对)PIDL 传递给带有标志 SIGDN_DESKTOPABSOLUTEPARSING 的SHGetNameFromIDList 最后这将返回一个 CLSID 字符串,我们可以使用 .lnk 文件的目标指定该字符串IShellLinkW::SetPath()。它按预期工作。

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

如果需要,可以使用 flag 获取正常显示名称SIGDN_NORMALDISPLAY,或者也可以通过调用主帖子评论框中提到的SHGetFileInfo函数来获得。


向建议我进行 PIDL 检索及其使用的用户致谢,因为我不确定要调查什么来解决这个问题。

我还将感谢 Vanara开源库,它帮助我在其源代码中找到每个 SH* 函数的正确 P/Invokes,特别是SHGetNameFromIDList的签名

于 2019-05-28T07:22:11.767 回答