Как создать ярлык (.lnk) с относительной целью?

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

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

Любые предложения, помимо очевидного размещения prog.exe в корневом каталоге?

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

Спасибо,

Рони

Ответы

Ответ 1

Хотя ярлыки могут содержать относительный путь к цели (файлы .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, которые он может читать от себя во время выполнения и т.д.).

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

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

Ответ 4

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

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

Ответ 5

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

Program.cmd

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

Program.ps1

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

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