[英]Update %PATH% environment variable using NSIS
我读过“超过 ${NSIS_MAX_STRLEN} (1024) 的字符串将被截断/损坏。”
如何安全地更新%PATH%
环境变量?
真正的解决方案是编写自定义插件或直接使用系统插件调用 Windows API,这样就可以避免 NSIS 缓冲区长度限制:
!include LogicLib.nsh
!include WinCore.nsh
!ifndef NSIS_CHAR_SIZE
!define NSIS_CHAR_SIZE 1
!endif
Function RegAppendString
System::Store S
Pop $R0 ; append
Pop $R1 ; separator
Pop $R2 ; reg value
Pop $R3 ; reg path
Pop $R4 ; reg hkey
System::Call 'ADVAPI32::RegCreateKey(i$R4,tR3,*i.r1)i.r0'
${If} $0 = 0
System::Call 'ADVAPI32::RegQueryValueEx(ir1,tR2,i0,*i.r2,i0,*i0r3)i.r0'
${If} $0 <> 0
StrCpy $2 ${REG_SZ}
StrCpy $3 0
${EndIf}
StrLen $4 $R0
StrLen $5 $R1
IntOp $4 $4 + $5
IntOp $4 $4 + 1 ; For \0
!if ${NSIS_CHAR_SIZE} > 1
IntOp $4 $4 * ${NSIS_CHAR_SIZE}
!endif
IntOp $4 $4 + $3
System::Alloc $4
System::Call 'ADVAPI32::RegQueryValueEx(ir1,tR2,i0,i0,isr9,*ir4r4)i.r0'
${If} $0 = 0
${OrIf} $0 = ${ERROR_FILE_NOT_FOUND}
System::Call 'KERNEL32::lstrlen(t)(ir9)i.r0'
${If} $0 <> 0
System::Call 'KERNEL32::lstrcat(t)(ir9,tR1)'
${EndIf}
System::Call 'KERNEL32::lstrcat(t)(ir9,tR0)'
System::Call 'KERNEL32::lstrlen(t)(ir9)i.r0'
IntOp $0 $0 + 1
!if ${NSIS_CHAR_SIZE} > 1
IntOp $0 $0 * ${NSIS_CHAR_SIZE}
!endif
System::Call 'ADVAPI32::RegSetValueEx(ir1,tR2,i0,ir2,ir9,ir0)i.r0'
${EndIf}
System::Free $9
System::Call 'ADVAPI32::RegCloseKey(ir1)'
${EndIf}
Push $0
System::Store L
FunctionEnd
Section
Push ${HKEY_CURRENT_USER}
Push "Environment"
Push "Path"
Push ";"
Push "c:\whatever"
Call RegAppendString
Pop $0
DetailPrint RegAppendString:Error=$0
SectionEnd
我更喜欢通过 NSIS nsExec::Exec
命令使用 windows 命令处理器 ( cmd.exe
),它允许您轻松地附加到PATH
如下:
; Check if the path entry already exists and write result to $0
nsExec::Exec 'echo %PATH% | find "c:\some\new\dir"'
Pop $0 ; gets result code
${If} $0 = 0
nsExec::Exec 'setx PATH=%PATH%;c:\some\new\dir'
${EndIf}
使用此方法, CMD.EXE
在内部扩展PATH
变量,不受任何 NSIS 字符串长度限制。 或者,改变的顺序%PATH%
如果你想被拾起你的程序了第一,任何和一切可能的系统由同一个名字上安装超前扫描记号粘贴:
nsExec::Exec 'setx PATH=c:\some\new\dir;%PATH%'
请注意,在构建新的PATH
时不要包含双引号很重要。 命令处理器从不希望在 PATH 字符串中有双引号,并且如果添加双引号,可能会以意想不到的方式运行。 它仅用分号 ( ;
) 分隔路径。
另请注意,此方法取决于Seki 在他的回答中解释的大字符串构建。
nsExec::Exec
与ExecWait
不同之处在于它在内部运行,不会弹出额外的可见 cmd 提示窗口。
我已经编写了 NSIS 3.0 示例来处理超过限制的情况并且不需要安装任何东西。 在这里回答了这个问题: Set environment variables with NSIS in Window 7
看着 NSIS 东西的所有复杂插件和字符限制,我感到很沮丧,所以我编写了一个名为 PathEd 的小应用程序来处理所有问题。
它旨在部署在您的安装程序中,可以像这样从其部署位置调用,例如:
PathEd.exe add "C:\\Program Files\\RepoZ"
或PathEd.exe remove "C:\\Program Files\\RepoZ"
PathEd 负责分号处理、避免重复、不区分大小写检查、用户帐户控制提示、参数引用处理、安全和防御性值删除等。
随意使用它。 但是,不要忘记在 GitHub 上给它一颗星。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.