如何创建具有相对目标的快捷方式 (.lnk)?

发布于 2024-09-12 22:03:02 字数 284 浏览 10 评论 0原文

我的钥匙盘上有一个可执行文件,位于 dir\program\prog.exe 我想要 DoK 根目录上的可执行文件的快捷方式,即 prog.lnk 引用 dir\program\prog.exe。

但是,prog.lnk 似乎不能有相对目标。当 DoK 分配有不同的驱动器号(具体取决于它所连接的 PC)时,就会出现问题。

除了将 prog.exe 放在根目录中这一显而易见的建议之外,还有什么建议吗?

(最终,我想在安装时使用 nsis 执行此操作)

谢谢,

Rony

I have an executable on my disk-on-key in dir\program\prog.exe
I'd like to have a shortcut to the executable on the DoK's root directory, that is, prog.lnk would refer to dir\program\prog.exe.

However, it seems that prog.lnk can't have a relative target. This is a problem when the DoK will have different drive letters assigned to it, depending on which PC it's connected to.

Any suggestions, aside from the obvious one of putting prog.exe in the root dir?

(ultimately, I'd like to do this at install time using nsis)

Thanks,

Rony

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

诺曦 2024-09-19 22:03:02

如果我们假设 cmd.exe 对于所有 Windows 安装都位于相同的绝对路径上(可能,但并非万无一失),您可以找出 .lnk 文件来启动 cmd,如下所示

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

/d 将目录设置为 .lnk 文件的目录。 lnk 文件

启动命令可能还有其他有用的选项(例如 /b)

If we assume cmd.exe would be on the same absolute path for all windows installations (probable, but not fool-proof) you can make out the .lnk file to start cmd like this

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

/d sets the directory to the directory of the .lnk file

There might be other useful options for the start command (e.g. /b)

马蹄踏│碎落叶 2024-09-19 22:03:02

虽然快捷方式可以包含目标的相对路径(.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 似乎可以工作,但我不确定是否会在生产代码中使用它

更好的解决方案是创建一个像 Oleg 建议的小 NSIS 应用程序(NSIS 应用程序可以在 .exe 末尾包含嵌入数据它可以在运行时从自身读取等......)

While it is possible for shortcuts to contain a relative path to the target (.lnk files have a flag called SLDF_HAS_RELPATH) NSIS does not support creating anything other than "normal" shortcuts so you need to write the binary data directly (The .lnk format is pretty stable and has been documented by 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

Call it like this:

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

While the generated .lnk seems to work, I'm not sure if I would use this in production code

A much better solution is to create a little NSIS app like Oleg suggests (NSIS applications can contain embedded data at the end of the .exe that it can read from itself at runtime etc..)

戏剧牡丹亭 2024-09-19 22:03:02

安装“Relative”

我正在使用一些技巧。该方法如下屏幕截图所示:

它启动 explorer.exe,然后传递一个相对路径像这样:

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

我为此使用名为“Relative”的小工具。安装后,您可以右键单击文件,然后选择创建相对快捷方式...。然后它会弹出一个另存为...框。这不像简单的拖放那么舒服,但它有帮助。 (它还为它创建的链接使用自己的特殊图标。因此链接中不再有原始图标。请参见上文。您可能喜欢也可能不喜欢这个。)

Install "Relative"

I'm using a bit of a hack. The approach is shown in this screenshot:

It starts explorer.exe and then passes a relative path like so:

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

I'm using a small tool called "Relative" for this. After you install it, you can right-click a file and then select Create relative shortcut.... It will then pop up a Save as... box. This is not quite as comfortable as simply dragging and dropping but it helps. (It also uses its own special icon for the links it creates. So you no longer have the original icon in the link. See above. You may or may not like this.)

压抑⊿情绪 2024-09-19 22:03:02

你是对的。您不能在可移动媒体上使用快捷方式(.lnk),因为就像您自己编写的那样,可移动媒体在不同情况下可以有不同的驱动器号。

如果您需要在驱动器的根目录中保存某些内容,请使用 CMD、VBS 或 JS 而不是快捷方式。在某些情况下,人们还使用标准 EXE,它使用 INI 文件等配置文件从另一个子目录启动另一个程序。 CD/DVD的典型做法是在插入盘后启动安装程序。也许这种方式也能满足您的要求?

You are right. You can not use shortcuts (.lnk) on a removable media, because like you wrote yourself the removable media can have different drive letters in different situations.

If you need to have something in a root directory of the drive one use a CMD, VBS or JS instead of a shortcut. In some situation one use also a standard EXE which use a config file like INI file to start another program from the other subdirectory. It is a typical practice for CD/DVD to implement starting of a setup program after inserting of the disk. Probably this way will be OK in for your requirements also?

绝對不後悔。 2024-09-19 22:03:02

我相信 NT 4 资源工具包命令 SHORTCUT.exe 将创建相对链接的快捷方式。我希望 Microsoft 能够创建一个新的受支持实用程序或 Powershell Cmdlet,以方便创建相关 .lnk 文件或使 NTFS 链接更像 Linux 符号链接。在此之前,我使用 .cmd/.bat 和 .ps1 文件来实现此目的。

Program.cmd

@"%~dp0Relative\Path\Program.exe" %*
  • @ = 禁止命令回显。
  • %~dp0 = 扩展到脚本的目录。
  • relative\path = 可以包含 .. 来备份目录。
  • %* = 将脚本接收到的任何参数传递给 Program.exe。

Program.ps1

不幸的是,虽然 .cmd/.bat 文件可以从任何上下文运行(运行对话框、CMD 提示符、Powershell、双击文件资源管理器等),但它们无法调用存储的内容在 UNC 路径上。为了在 Powershell 中公开 UNC 路径中的内容(我为 Git 和 Mercurial 等工具执行此操作),我将创建上述脚本的 Powershell 版本。

&"$PSScriptRoot\Relative\Path\Program.exe" @args
  • & = 将 Powershell 置于命令模式,以便运行引号中的字符串。
  • "" = 包含一个字符串,扩展所有变量。
  • $PSScriptRoot = 展开到脚本的目录。
  • relative\path = 可以包含 .. 来备份目录。
  • @args = 将脚本接收到的任何参数传递给 Program.exe。

I believe that the NT 4 Resource Kit command SHORTCUT.exe would create relative linked shortcuts. I wish that Microsoft would create a new supported utility or Powershell Cmdlet to facilitate the creation of relative .lnk files or make NTFS links work more like Linux symbolic links. Until then, I use .cmd/.bat and .ps1 files for this purpose.

Program.cmd

@"%~dp0Relative\Path\Program.exe" %*
  • @ = Suppresses the command echo.
  • %~dp0 = expands to the script's directory.
  • Relative\Path = could include .. to backup a directory.
  • %* = passes any parameters received by the script on to Program.exe.

Program.ps1

Unfortunately, though .cmd/.bat files will run from any context (the run dialog, a CMD prompt, in Powershell, double clicking in File Explorer, etc), they cannot call things stored on a UNC path. For exposing things in a UNC path, in Powershell (I do this for tools like Git and Mercurial), I will create a Powershell version of the above script.

&"$PSScriptRoot\Relative\Path\Program.exe" @args
  • & = puts Powershell into command mode, so that the string in quotes gets ran.
  • "" = contains a string, expanding any variables.
  • $PSScriptRoot = expands to the script's directory.
  • Relative\Path = could include .. to backup a directory.
  • @args = passes any parameters received by the script on to Program.exe.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文