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

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

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

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

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

Спасибо,

Rony

14
задан ronys 5 August 2010 в 19:42
поделиться

3 ответа

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

8
ответ дан 1 December 2019 в 12:26
поделиться

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

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

1
ответ дан 1 December 2019 в 12:26
поделиться

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

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

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

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

11
ответ дан 1 December 2019 в 12:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: