Как мне создать ярлык (.lnk) с относительной целью? - PullRequest
14 голосов
/ 05 августа 2010

У меня есть исполняемый файл на моем диске в ключе в каталоге dir \ program \ prog.exe Я хотел бы иметь ярлык для исполняемого файла в корневом каталоге DoK, то есть prog.lnk будет ссылаться на dir \ program \ prog.exe.

Однако, похоже, что у prog.lnk не может быть относительной цели. Это проблема, когда DoK назначают разные буквы дисков в зависимости от того, к какому компьютеру он подключен.

Есть ли какие-либо предложения, кроме очевидного - поместить prog.exe в корневой каталог?

(в конечном счете, я хотел бы сделать это во время установки, используя nsis)

Спасибо

Rony

Ответы [ 5 ]

11 голосов
/ 24 августа 2010

Если мы предположим, что cmd.exe будет находиться на одном и том же абсолютном пути для всех установок Windows (вероятно, но не защищено от ошибок), вы можете создать файл .lnk для запуска cmd следующим образом

cmd.exe /c start /d. your command here

/ d устанавливает каталог в каталог .lnk файла

Могут быть и другие полезные опции для команды запуска (например, / b)

8 голосов
/ 06 августа 2010

Хотя ярлыки могут содержать относительный путь к цели (файлы .lnk имеют флаг SLDF_HAS_RELPATH ) NSIS не поддерживает создание чего-либо, кроме "обычных" ярлыков, поэтому вам нужно написать напрямую двоичные данные (формат .lnk довольно стабилен и задокументирован MS)

!macro FileWriteHexBytes h b
push ${h}
push ${b}
call FileWriteHexBytes
!macroend
Function FileWriteHexBytes
exch $9
exch
exch $0
push $1
push $2
loop:
    StrCpy $2 $9 2
    StrLen $1 $2
    IntCmp $1 2 0 end
    FileWriteByte $0 "0x$2"
    StrCpy $9 $9 "" 2
    goto loop
end:
pop $2
pop $1
pop $0
pop $9
FunctionEnd


Function CreateRelativeLnk
exch $9
exch
exch $0
push $1
FileOpen $0 "$0" w
StrCmp $0 "" clean
!insertmacro FileWriteHexBytes $0 "4C0000000114020000000000C000000000000046"
!insertmacro FileWriteHexBytes $0 48010400 ;flags
!insertmacro FileWriteHexBytes $0 00000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000

StrLen $1 $9 ;must be < 255!
FileWriteByte $0 $1
FileWriteByte $0 0
FileWrite $0 "$9" ;relative target path

!if 0
;The icon is problematic, does not seem like it works with relative paths (but you can use system icons...)
StrCpy $9 "explorer.exe"
StrLen $1 $9
FileWriteByte $0 $1
FileWriteByte $0 0
FileWrite $0 "$9"
!else
!insertmacro FileWriteHexBytes $0 05003e2e657865 ;fake default .exe icon
!endif

clean:
FileClose $0
pop $1
pop $0
pop $9
FunctionEnd

Назовите это так:

push "$temp\testlink.lnk"
push "testdir\testapp.exe" ;full path to this is $temp\testdir\testapp.exe
call CreateRelativeLnk

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

Гораздо лучшим решением является создание небольшого приложения NSIS, как предлагает Олег (приложения NSIS могут содержать встроенные данные в конце .exe, которые они могут читать из себя во время выполнения и т. Д.)

3 голосов
/ 04 сентября 2013

Установить "Относительный"

Я использую немного хака. Подход показан на этом скриншоте:

Запускает файл explorer.exe, а затем передает относительный путь следующим образом:

%windir%\explorer.exe path\to\your\files\youFileName.example

Для этого я использую небольшой инструмент под названием "Относительный" . После установки вы можете щелкнуть правой кнопкой мыши файл и выбрать Create relative shortcut.... Затем появится окно Save as.... Это не так удобно, как просто перетаскивание, но это помогает. (Он также использует свой собственный специальный значок для создаваемых ссылок. Таким образом, у вас больше нет исходного значка в ссылке. См. Выше. Вам может понравиться или не понравиться это.)

1 голос
/ 06 августа 2010

Вы правы.Вы не можете использовать ярлыки (.lnk) на съемном носителе, потому что, как и вы сами, съемный носитель может иметь разные буквы дисков в разных ситуациях.

Если вам нужно что-то в корневом каталоге дискаодин использует CMD, VBS или JS вместо ярлыка.В некоторых ситуациях можно использовать также стандартный EXE-файл, который использует конфигурационный файл, такой как INI-файл, для запуска другой программы из другого подкаталога.Для CD / DVD это обычная практика: запуск программы установки после установки диска.Вероятно, этот путь тоже подойдет для ваших требований?

0 голосов
/ 29 мая 2016

Я считаю, что команда NT 4 Resource Kit SHORTCUT.exe создаст относительные связанные ярлыки. Мне бы хотелось, чтобы Microsoft создала новую поддерживаемую утилиту или командлет Powershell для облегчения создания относительных файлов .lnk или чтобы ссылки NTFS работали больше как символические ссылки Linux. До этого я использую файлы .cmd / .bat и .ps1 для этой цели.

Program.cmd

@"%~dp0Relative\Path\Program.exe" %*
  • @ = Подавляет эхо команды.
  • % ~ dp0 = раскрывается в каталог скрипта.
  • Относительный \ Path = может включать .. для резервного копирования каталога.
  • % * = передает все параметры, полученные сценарием, в Program.exe.

Program.ps1

К сожалению, хотя файлы .cmd / .bat будут запускаться из любого контекста (диалоговое окно запуска, приглашение CMD, в Powershell, двойной щелчок в проводнике и т. Д.), Они не могут вызывать вещи, хранящиеся по пути UNC. Для демонстрации вещей в пути UNC в Powershell (я делаю это для таких инструментов, как Git и Mercurial), я создам версию приведенного выше сценария Powershell.

&"$PSScriptRoot\Relative\Path\Program.exe" @args
  • & = переводит Powershell в командный режим, поэтому запускается строка в кавычках.
  • "" = содержит строку, расширяющую любые переменные.
  • $ PSScriptRoot = раскрывается в каталог скрипта.
  • Относительный \ Path = может включать .. для резервного копирования каталога.
  • @ args = передает все параметры, полученные сценарием, в Program.exe.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...