IShellLinkW :: GetPath (SLGP_RAWPATH) не возвращает «сырую» цель файла lnk - PullRequest
1 голос
/ 27 мая 2019

Я заметил, что метод 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, который указывает на файл или каталог. Он не может получить цель, которая указывает на специальный элемент / виртуальные папки.

Мои вопросы:

Это задумано? Если нет, то что я пропускаю или делаю не так? (может быть, мои определения неверны?). И что мне нужно сделать, чтобы получить специальную цель? Обратите внимание, что я хотел бы получить цель, чтобы отобразить ее в PropertyGrid, а также создать новую цель с клоном специальной цели.

Обратите внимание, что язык программирования, на котором я разработал этот код, не имеет значения, потому что я сначала прошу об ориентации, а также я принимаю любое решение, написанное на C #.

1 Ответ

1 голос
/ 28 мая 2019

Как упомянуто в поле для комментариев основного сообщения, чтобы извлечь необработанную цель ссылки оболочки, которая указывает на специальный путь не в файловой системе (например, «Мой компьютер»), сначала нам нужно получить PIDL по телефону IShellLinkW::GetIDList().

Далее мы передаем этот (абсолютный) PIDL SHGetNameFromIDList с флагом SIGDN_DESKTOPABSOLUTEPARSING , и, наконец, это вернет строку CLSID, которую мы можем указать для цели .lnk файл с IShellLinkW::SetPath(). Работает как положено.

Обратите внимание, что я не уверен, что могут существовать специальные сценарии (редкие цели файла lnk), по которым это может работать не так, как ожидалось. Я не нашел этот случай ошибки.

И, если необходимо, обычное отображаемое имя можно получить с помощью флага SIGDN_NORMALDISPLAY, а также путем вызова функции SHGetFileInfo , как указано в поле для комментариев основного сообщения.


Кредиты для пользователей, которые предложили мне поиск PIDL и его использование, потому что я не был уверен, что нужно исследовать, чтобы решить эту проблему.

Я также дам кредиты Vanara библиотеке с открытым исходным кодом, которая помогла мне найти правильный P / Вызывает каждую функцию SH * в их исходном коде, особенно подпись для SHGetNameFromIDList .

...