在工作目录中使用环境变量创建快捷方式
Create shortcut with environment variable in working directory
目前我正在创建一个快捷方式:
SetShellVarContext all
SetOutPath "$INSTDIR"
CreateShortCut "$SMPROGRAMS\MyApp.lnk" "$INSTDIR\MyApp.exe"
我想将此快捷方式的工作目录从 C:\Program Files\MyApp
更改为 %UserProfile%
。
棘手的部分是我不想%UserProfile%
展开,我想把它作为一个环境变量,所以程序在当前用户的配置文件目录中启动。
我可以用 NSIS 实现吗?如果没有,最简单的解决方法是什么?
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 ; New working directory
Exch
Exch ; Path
Push [=11=] ; HRESULT
Push ; IShellLink
Push ; IPersistFile
System::Call 'OLE32::CoCreateInstance(g "${CLSID_ShellLink}",i 0,i ${CLSCTX_INPROC_SERVER},g "${IID_IShellLink}",*i.r1)i.r0'
${If} [=11=] = 0
System::Call `->0(g "${IID_IPersistFile}",*i.r2)i.r0`
${If} [=11=] = 0
System::Call `->5(wr8,i${STGM_READWRITE})i.r0` ; Load
${If} [=11=] = 0
System::Call `->9(tr9)i.r0` ; SetWorkingDirectory
${If} [=11=] = 0
System::Call `->6(i0,i0)i.r0` ; Save
${EndIf}
${EndIf}
System::Call `->2()` ; Release
${EndIf}
System::Call `->2()` ; Release
${EndIf}
StrCpy [=11=]
Pop
Pop [=11=]
Pop
Exch
FunctionEnd
Section
CreateShortcut "$temp\test2.lnk" "$sysdir\Calc.exe"
Push "$temp\test2.lnk"
Push "%UserProfile%"
Call Lnk_SetWorkingDirectory
Pop [=11=]
DetailPrint HRESULT=[=11=] ; 0 = success
SectionEnd
需要注意的是 IShellLink::SetWorkingDirectory 并没有说明支持未扩展的环境变量,但它们似乎确实有效。
目前我正在创建一个快捷方式:
SetShellVarContext all
SetOutPath "$INSTDIR"
CreateShortCut "$SMPROGRAMS\MyApp.lnk" "$INSTDIR\MyApp.exe"
我想将此快捷方式的工作目录从 C:\Program Files\MyApp
更改为 %UserProfile%
。
棘手的部分是我不想%UserProfile%
展开,我想把它作为一个环境变量,所以程序在当前用户的配置文件目录中启动。
我可以用 NSIS 实现吗?如果没有,最简单的解决方法是什么?
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 ; New working directory
Exch
Exch ; Path
Push [=11=] ; HRESULT
Push ; IShellLink
Push ; IPersistFile
System::Call 'OLE32::CoCreateInstance(g "${CLSID_ShellLink}",i 0,i ${CLSCTX_INPROC_SERVER},g "${IID_IShellLink}",*i.r1)i.r0'
${If} [=11=] = 0
System::Call `->0(g "${IID_IPersistFile}",*i.r2)i.r0`
${If} [=11=] = 0
System::Call `->5(wr8,i${STGM_READWRITE})i.r0` ; Load
${If} [=11=] = 0
System::Call `->9(tr9)i.r0` ; SetWorkingDirectory
${If} [=11=] = 0
System::Call `->6(i0,i0)i.r0` ; Save
${EndIf}
${EndIf}
System::Call `->2()` ; Release
${EndIf}
System::Call `->2()` ; Release
${EndIf}
StrCpy [=11=]
Pop
Pop [=11=]
Pop
Exch
FunctionEnd
Section
CreateShortcut "$temp\test2.lnk" "$sysdir\Calc.exe"
Push "$temp\test2.lnk"
Push "%UserProfile%"
Call Lnk_SetWorkingDirectory
Pop [=11=]
DetailPrint HRESULT=[=11=] ; 0 = success
SectionEnd
需要注意的是 IShellLink::SetWorkingDirectory 并没有说明支持未扩展的环境变量,但它们似乎确实有效。