Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Путь до объекта по ярлыку (FileGetSymLinkTarget) / 16 сообщений из 16, страница 1 из 1
25.10.2017, 12:48:57
    #39541626
SOFT FOR YOU
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
procedure Test;
var
  S: string;
begin
  if (FileGetSymLinkTarget('C:\Users\Дмитрий\Desktop\Delphi 10.1 Berlin.lnk', S)) then
    ShowMessage(S)
  else
    ShowMessage('none');
end;



Показывается "none"
Что я делаю не так?

В интернете увидел вот такую штуку (типа особенная реализация под винду). Но возвращается фигня.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
function FileGetSymLinkTarget(const FileName: string; var TargetName: string): Boolean;
var
  LinkHandle: THandle;
  Buffer: array [0..512] of Char;
begin
  Result := False;

  LinkHandle := CreateFile(PChar(FileName), 0, FILE_SHARE_READ, nil,
      OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  if (LinkHandle <> INVALID_HANDLE_VALUE) then
  try
    if (GetFinalPathNameByHandle(LinkHandle, Buffer, High(Buffer), FILE_NAME_NORMALIZED) > 0) then
    begin
      TargetName := Buffer;
      Result := True;
    end;
  finally
    CloseHandle(LinkHandle);
  end;
end;
...
Рейтинг: 0 / 0
25.10.2017, 12:54:55
    #39541640
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
Symlink и ярлык не путаешь?
...
Рейтинг: 0 / 0
25.10.2017, 13:48:30
    #39541717
SOFT FOR YOU
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
wadman,

Может и путаю. А как по ярлыку узнать путь до объекта?
Желательно кроссплатформ
...
Рейтинг: 0 / 0
25.10.2017, 14:05:24
    #39541746
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
SOFT FOR YOUЖелательно кроссплатформ
lnk - это виндовое изобретение.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb774950(v=vs.85).aspx
...
Рейтинг: 0 / 0
25.10.2017, 14:11:07
    #39541754
SOFT FOR YOU
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
wadman,

А в Линуксах и Макосях чем обходятся? Есть же рабочий стол, вся фигня
...
Рейтинг: 0 / 0
25.10.2017, 14:14:35
    #39541762
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
Зависит от оболочки. Про все не скажу, но в кде это как ини-файл.
...
Рейтинг: 0 / 0
25.10.2017, 14:29:43
    #39541787
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
SOFT FOR YOUА в Линуксах и Макосях чем обходятся?
Чем на макоси не знаю, а на линуксе это обычный текстовый файл *.desktop соответствующий спецификации Desktop Entry .
...
Рейтинг: 0 / 0
25.10.2017, 18:15:49
    #39541973
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
SOFT FOR YOU,

IShellLink если по простому

PS: неправильно работает в ряде случаев. если нужно всегда, то только самому парсить
...
Рейтинг: 0 / 0
27.10.2017, 02:49:08
    #39542932
JayDi
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
Вот тут есть решение от Рея Конопки . Ниже мой переделанный вариант с распознаванием реальных путей из lnk-файлов и раскрытием их с коротких имен до полных (например, используется для обработки перетаскиваемых файлов из проводника в приложение):

получаем реальный путь к файлу из ярлыка
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
function GetRealLinkFile(const AFileFullName: string): string;
var
  source: string;
  link: IShellLinkW;
  linkFile: IPersistFile;
  shortPath: array[0..MAX_PATH] of Char;
  findData: TWin32FindData;
  isNeedUninitialize: Boolean;

  function GetLongName(const AFile: string): string;
  var
    longPath: string;
    sz: Integer;
  begin
    // делает из короткого имени длинное
    // см. реализацию в IOUtils.TPath.GetTempPath
    if AFile.Contains('~') then
    begin
      sz := GetLongPathName(PChar(AFile), nil, 0);
      SetLength(longPath, sz - 1);
      GetLongPathName(PChar(AFile), PChar(longPath), sz);
      Result := longPath;
    end
    else
    begin
      Result := AFile;
    end;
  end;

  function CustomFileExists(const AFile: string): Boolean;
  begin
    if AFile.StartsWith('\\') then
    begin
      Result := TFile.Exists(source);
    end
    else
    begin
      Result := TFile.Exists('\\?\' + source);
    end;
  end;

begin
  // получает реальный путь к файлу с учетом ярлыка и преобразует короткое имя с ~ в полное
  // только для windows
  // автор jaydi85@gmail.com
  // на основе https://forums.embarcadero.com/thread.jspa?threadID=171700
  // и https://stackoverflow.com/questions/16874118/delphi-how-to-check-if-a-file-exists-path-over-255-characters
  source := GetLongName(AFileFullName);
  Result := source;

  if (AnsiLowerCase(ExtractFileExt(source)) <> '.lnk') or not CustomFileExists(source) then
  begin
    Exit;
  end;

  // инициализация COM, если код будет вызван из не основного потока или библиотеки
  isNeedUninitialize := SUCCEEDED(CoInitializeEx(nil, COINIT_APARTMENTTHREADED or COINIT_DISABLE_OLE1DDE));
  try
    // ярлык грузится в ShellLink и оттуда вытаскивается адрес
    OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLinkW, link));
    try
      OleCheck(link.QueryInterface(IPersistFile, linkFile));
      try
        OleCheck(linkFile.Load(PWideChar(source), STGM_READ));
        OleCheck(link.Resolve(0, SLR_ANY_MATCH or SLR_NO_UI));
        OleCheck(link.GetPath(shortPath, MAX_PATH, findData, SLGP_SHORTPATH));

        Result := GetLongName(shortPath);
      finally
        linkFile := nil;
      end;
    finally
      link := nil;
    end;
  finally
    if isNeedUninitialize then
    begin
      CoUninitialize;
    end;
  end;
end;



P.S. Тестировалось не во всех версиях винды и не со всеми извращенными путями
...
Рейтинг: 0 / 0
27.10.2017, 10:01:14
    #39543018
SOFT FOR YOU
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
JaDi,

Красавчик ;)
Спасибо
...
Рейтинг: 0 / 0
27.10.2017, 10:36:59
    #39543043
Aniskin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
Известный баг (особенность) использования IShellLink в x64 системах - если ссылка ссылается на файл в %PROGRAM FILES%, то при использовании данного метода в 32 битном приложении метод может отдать имя из %PROGRAM FILES (x86)%. Может быть пригодится - мой код , который читает содержимое lnk файла прямым чтением структур файла.
...
Рейтинг: 0 / 0
27.10.2017, 11:14:25
    #39543070
SOFT FOR YOU
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
Aniskin,

Это огонь!
...
Рейтинг: 0 / 0
27.10.2017, 11:18:55
    #39543075
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
В линуксе всё сильно проще:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
function ExtractTarget(const ADesktopFileName : String) : String;
const

 Entry = 'desktop entry';

begin

  with TIniFile.Create(ADesktopFileName, [ifoStripQuotes]) do
   try

    case LowerCase(ReadString(Entry, 'type', '')) of

     'application' : Result := ReadString(Entry, 'exec', '');

     'link'        : begin

                      Result := ReadString(Entry, 'url', '');

                      if Pos('file://', Result) = 1 then
                       Delete(Result, 1, 7)
                      else
                       Result := '';

                     end;

    else

     Result := '';

    end;

   finally

    Free;

   end;

end;
...
Рейтинг: 0 / 0
27.10.2017, 12:03:54
    #39543121
SOFT FOR YOU
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
Давайте ещё для полноты картины код под Макось и телефоны :)
...
Рейтинг: 0 / 0
27.10.2017, 12:04:39
    #39543122
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
SOFT FOR YOUAniskin,

Это огонь!с миру по нитке и наберёшь гляди
добавлю баг для этого кода: ярлык сафари попробуй прочитать
...
Рейтинг: 0 / 0
27.10.2017, 12:30:41
    #39543157
Aniskin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Путь до объекта по ярлыку (FileGetSymLinkTarget)
kealon(Ruslan)добавлю баг для этого кода: ярлык сафари попробуй прочитатьМожешь выложить этот ярлык? Хочется глянуть на причину проблемы.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Путь до объекта по ярлыку (FileGetSymLinkTarget) / 16 сообщений из 16, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]