首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用NSIS更新%PATH%环境变量

使用NSIS更新%PATH%环境变量
EN

Stack Overflow用户
提问于 2015-07-10 20:30:06
回答 5查看 7.3K关注 0票数 12

我读过这样一篇文章:“字符串长度超过${NSIS_MAX_STRLEN} (1024)将被截断/损坏。”

如何安全地更新%PATH%环境变量? How I safely %PATH% environment variable?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-07-10 20:56:53

您可以使用来自special builds page的替代NSIS构建,比如定义NSIS_MAX_STRLEN=8192large strings build,它应该可以防止您破坏主机路径。

实际上,在台式机上,1024字节似乎足够了,但在安装了许多工具的开发主机上(比如我的),路径在操作后可能会中断,而构建的8192字节的字符串从未扰乱过我的机器。

为了非常确定,您可以在操作之前添加对路径长度的检查,并在路径接近NSIS_MAX_STRLEN常量的情况下尝试操作它之前中止安装程序并显示一条消息。

票数 7
EN

Stack Overflow用户

发布于 2015-07-10 21:33:00

真正的解决方案是编写一个自定义插件或直接使用系统插件调用Windows API,这样就可以避免NSIS缓冲区长度限制:

代码语言:javascript
复制
!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 
票数 5
EN

Stack Overflow用户

发布于 2018-02-01 10:20:39

我更喜欢通过NSIS nsExec::Exec命令使用windows命令处理器(cmd.exe),它允许您轻松地添加到PATH,如下所示:

代码语言:javascript
复制
; 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%标记粘贴的顺序,然后使用相同的名称获取系统上可能安装的所有其他内容:

代码语言:javascript
复制
    nsExec::Exec 'setx PATH=c:\some\new\dir;%PATH%'

请注意,在构建新的PATH时,不要使用双引号,这一点很重要。命令处理程序永远不会在路径字符串中使用双引号,如果您添加了任何双引号,命令处理程序可能会以意外的方式运行。它仅使用分号(;)分隔路径。

另请注意,此方法依赖于作为explained by Seki in his answerlarge strings build

nsExec::ExecExecWait的不同之处在于,它在内部运行,不会弹出额外的可视命令提示窗口。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31340823

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档