簡體   English   中英

使用 NSIS 更新 %PATH% 環境變量

[英]Update %PATH% environment variable using NSIS

我讀過“超過 ${NSIS_MAX_STRLEN} (1024) 的字符串將被截斷/損壞。”

如何安全地更新%PATH%環境變量?

您可以使用來自特殊構建頁面的替代 NSIS 構建,例如定義NSIS_MAX_STRLEN=8192大字符串構建,並且應該可以防止您破壞主機路徑。

實際上,在台式機上,1024 字節似乎足夠了,但是在安裝了許多工具的開發主機上(如我的),路徑可能在操作后被破壞,而 8192 字節的字符串構建從未干擾過我的機器。

可以肯定的是,您可以在操作之前添加對路徑長度的檢查,並在嘗試操作之前路徑接近NSIS_MAX_STRLEN常量的情況下使用消息中止安裝程序。

真正的解決方案是編寫自定義插件或直接使用系統插件調用 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::ExecExecWait不同之處在於它在內部運行,不會彈出額外的可見 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 上給它一顆星。

https://github.com/awaescher/PathEd

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM