Update% PATH% environment variable with NSIS

I read that "Lines longer than $ {NSIS_MAX_STRLEN} (1024) will be truncated / corrupted."

How can I safely update% of the PATH% environment variable?

+5
source share
4 answers

You can use an alternative NSIS line from a special build page , for example large strings build , which defines NSIS_MAX_STRLEN=8192 and should prevent you from breaking the host path.

In practice, on a desktop computer, 1024 bytes seems to be enough, but on a development host with many tools installed (for example, mine), the path may be damaged after the manipulation, while a string of 8192 bytes strings never caused concern in my machine.

To be sure, you can add a path length check before manipulation and abort the installation with a message if the path is close to the constant NSIS_MAX_STRLEN before trying to manipulate it.

+5
source

The real solution is to write your own plugin or call the Windows API directly with the system plugin so that you can avoid limiting the length of the NSIS buffer:

 !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 
+4
source

I prefer to use the Windows shell ( cmd.exe ) with the NSIS nsExec::Exec command, which makes it easy to add to PATH like this:

 ; 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} 

Using this method, cmd.exe internally extends the PATH variable, which is safe from any NSIS string length restrictions. Alternatively, change the insertion order of %PATH% token if you want your program to be lifted first, ahead of everything else that can be installed on the system with the same name:

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

Also note that when creating a new PATH it is important not to include double quotes. The shell never expects double quotes in the PATH string and can behave in unpredictable ways if you add them. It limits the paths to only a semicolon ( ; ).

nsExec::Exec differs from ExecWait in that it works internally without causing additional cmd prompt windows to be visible.

+1
source

I wrote an NSIS 3.0 example to handle cases longer than the limit and without having to install anything. The answer to the question here: Set environment variables with NSIS in window 7

0
source

All Articles