2015-07-10 187 views

回答

5

您可以使用special builds page中的替代NSIS版本,如large strings build定義NSIS_MAX_STRLEN=8192,並應阻止您破壞主機路徑。實際上,在桌面計算機上,1024字節似乎夠用了,但是在安裝了許多工具的開發主機上(如我的),路徑可能會在操作後中斷,而8192字節的字符串從未擾亂我的機器。

可以肯定的是,您可以在操作之前在路徑長度上添加一個檢查,並在路徑接近常量NSIS_MAX_STRLEN,然後嘗試操縱它,然後用消息中止安裝程序。

4

真正的解決辦法是寫一個自定義插件或直接與系統插件調用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 
+0

我只是做對RegAppendString功能輕微的測試,最好你將迫使零終止,檢查它是否已經在最後的分離器,並執行所有這一切都在一個循環,以避免與調用函數RegQueryValueEx之間的串變化問題。 – Anders

1

我更喜歡通過NSIS nsExec::Exec命令,它允許你要追加到PATH容易,像這樣使用Windows命令處理器(cmd.exe):

; 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 'set PATH=%PATH%;c:\some\new\dir' 
${EndIf} 

使用這種方法,CMD.EXE擴張內部變量PATH,不受任何NSIS字符串長度限制的影響。

nsExec::Exec 'set PATH=c:\some\new\dir;%PATH%' 

還要注意的是:另外,如果你想被拾起你的程序第一,任何事情和其他一切可能對系統由同名安裝提前改變%PATH%標記粘貼順序包括雙引號,而建設新PATH是很重要的。命令處理器從不期望PATH字符串中的雙引號,如果添加任何內容,可能會以意想不到的方式運行。它僅用分號(;)分隔路徑。

nsExec::ExecExecWait不同之處在於它在內部運行,沒有彈出額外可見命令提示符窗口。