【问题标题】:How do I create a shortcut (.lnk) with a relative target?如何创建具有相对目标的快捷方式 (.lnk)?
【发布时间】:2011-03-26 00:22:47
【问题描述】:

我的磁盘上的 dir\program\prog.exe 中有一个可执行文件 我想在 DoK 的根目录上有一个可执行文件的快捷方式,即 prog.lnk 将引用 dir\program\prog.exe。

但是,prog.lnk 似乎没有相对目标。当 DoK 分配不同的驱动器号时,这是一个问题,具体取决于它连接到的 PC。

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

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

谢谢,

罗尼

【问题讨论】:

    标签: windows installation nsis shortcut


    【解决方案1】:

    如果我们假设 cmd.exe 对于所有 Windows 安装都在同一个绝对路径上(可能,但不是万无一失),您可以找出 .lnk 文件来像这样启动 cmd

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

    /d 设置目录为.lnk文件所在目录

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

    【讨论】:

      【解决方案2】:

      虽然快捷方式可以包含到目标的相对路径(.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 的末尾包含嵌入式数据,它可以在运行时从自身读取等。)

      【讨论】:

      【解决方案3】:

      安装“相对”

      我正在使用一些技巧。该方法显示在此屏幕截图中:

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

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

      我为此使用small tool called "Relative"。安装后,您可以右键单击一个文件,然后选择Create relative shortcut...。然后它会弹出一个Save as... 框。这不像简单的拖放那样舒服,但它有帮助。 (它还为它创建的链接使用自己的特殊图标。因此,链接中不再有原始图标。见上文。您可能喜欢也可能不喜欢。)

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

          我相信 NT 4 Resource Kit 命令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 路径中的内容。为了在 UNC 路径中公开内容,在 Powershell 中(我为 Git 和 Mercurial 等工具执行此操作),我将创建上述脚本的 Powershell 版本。

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

          【讨论】:

            猜你喜欢
            • 2013-08-04
            • 1970-01-01
            • 2017-04-25
            • 2012-05-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多