【问题标题】:Create shortcut with environment variable in working directory在工作目录中使用环境变量创建快捷方式
【发布时间】:2015-11-28 15:07:01
【问题描述】:

目前我正在创建一个快捷方式:

SetShellVarContext all
SetOutPath "$INSTDIR"
CreateShortCut "$SMPROGRAMS\MyApp.lnk" "$INSTDIR\MyApp.exe"

我想将此快捷方式的工作目录从C:\Program Files\MyApp 更改为%UserProfile%

棘手的部分是我不想%UserProfile%被扩展,我想把它作为一个环境变量,所以程序从当前用户的配置文件目录开始。

我可以通过 NSIS 实现这一目标吗?如果没有,最简单的解决方法是什么?


参考:CreateShortcut

【问题讨论】:

    标签: installation nsis shortcut


    【解决方案1】:

    NSIS 使用 SetOutPath ($OutDir) 设置的路径在快捷方式上调用 IShellLink::SetWorkingDirectory

    可以将$OutDir 设置为无效路径,然后调用 CreateShortcut:

    Push $OutDir ; Save
    StrCpy $OutDir "%UserProfile%"
    CreateShortcut "$temp\test1.lnk" "$sysdir\Calc.exe"
    Pop $OutDir ; Restore
    

    它确实有效,但可能有点违反规则。您也可以在不依赖未记录的 NSIS 怪癖的情况下做到这一点:

    !define CLSCTX_INPROC_SERVER 1
    !define STGM_READWRITE 2
    !define IID_IPersistFile {0000010b-0000-0000-C000-000000000046}
    !define CLSID_ShellLink {00021401-0000-0000-c000-000000000046}
    !define IID_IShellLinkA {000214ee-0000-0000-c000-000000000046}
    !define IID_IShellLinkW {000214f9-0000-0000-c000-000000000046}
    !ifdef NSIS_UNICODE
    !define IID_IShellLink ${IID_IShellLinkW}
    !else
    !define IID_IShellLink ${IID_IShellLinkA}
    !endif
    
    !include LogicLib.nsh
    Function Lnk_SetWorkingDirectory
    Exch $9 ; New working directory 
    Exch
    Exch $8 ; Path
    Push $0 ; HRESULT
    Push $1 ; IShellLink
    Push $2 ; IPersistFile
    System::Call 'OLE32::CoCreateInstance(g "${CLSID_ShellLink}",i 0,i ${CLSCTX_INPROC_SERVER},g "${IID_IShellLink}",*i.r1)i.r0'
    ${If} $0 = 0
        System::Call `$1->0(g "${IID_IPersistFile}",*i.r2)i.r0`
        ${If} $0 = 0
            System::Call `$2->5(wr8,i${STGM_READWRITE})i.r0` ; Load
            ${If} $0 = 0
                System::Call `$1->9(tr9)i.r0` ; SetWorkingDirectory
                ${If} $0 = 0
                    System::Call `$2->6(i0,i0)i.r0` ; Save
                ${EndIf}
            ${EndIf}
            System::Call `$2->2()` ; Release
        ${EndIf}
        System::Call `$1->2()` ; Release
    ${EndIf}
    StrCpy $9 $0
    Pop $1
    Pop $0
    Pop $8
    Exch $9
    FunctionEnd
    
    Section
    CreateShortcut "$temp\test2.lnk" "$sysdir\Calc.exe"
    Push "$temp\test2.lnk"
    Push "%UserProfile%"
    Call Lnk_SetWorkingDirectory 
    Pop $0
    DetailPrint HRESULT=$0 ; 0 = success
    SectionEnd
    

    需要注意的是,IShellLink::SetWorkingDirectory 没有说明支持未扩展的环境变量,但它们似乎确实有效。

    【讨论】:

    • 谢谢!除了你的解决方案,我能看到的只是调用一个 VB 脚本。您的第二个解决方案有点太麻烦了,但您的第一个解决方案应该不会那么糟糕(一个普通的字符串被传递给$OutDirIShellLink::SetWorkingDirectory,他们只是照原样接受)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 2021-10-04
    • 2010-09-19
    • 1970-01-01
    • 2018-11-06
    相关资源
    最近更新 更多