2012-10-16 2 views
0

NSIS 설치 프로그램을 사용하여 환경 변수를 설정하고 싶습니다. 중요한 경우 Windows 7에서 스크립트를 실행합니다. 감사합니다.Window 7에서 NSIS로 환경 변수를 설정하십시오.

+0

무엇을 위해 그들을 설정? 자식 프로세스? 영구 사용자 또는 컴퓨터 전체? – Anders

+0

죄송합니다. 귀하의 질문에 답변하기 위해 NSIS도 잘 모릅니다.설치 과정에서 새 변수를 추가하기 만하면됩니다. 감사! –

+0

내 질문은 NSIS에 특정한 것이 아니며 이러한 "부속 유형"은 Windows에 존재합니다 (기본적으로 그들이 어디서 왔는지, 어디서 영향을 미치는지) – Anders

답변

1

How can I create or change an environment variable

참고 :이 방법은 안전하고 %path%을 변경 손상 될 수 있습니다 항목이 더 이상 NSIS 문자열 길이보다 긴 경우!

+0

"안전한"방법이 있습니까? 감사! –

+0

시스템 플러그 인을 사용하여 메모리를 할당하고 문자열과 레지스트리 함수를 직접 호출해야합니다. 그렇게하는 샘플 코드가 존재하지 않는다고 생각합니다 ... – Anders

1

당신은 윈도우 배치 파일을 만들 단지 다른 파일과 같은 설정으로 팩에 플러그인 디렉토리로 압축을 풀고 설치하고 실행할 수 있습니다

File "/oname=$PluginsDir\appendvar.bat" "PathToScriptDir\appendvar.bat" 

nsExec::ExecToLog '"$SYSDIR\cmd.exe" /C "$PluginsDir\appendvar.bat" -g -all' 
Pop $R0 ; last error 

Delete "$PluginsDir\appendvar.bat" 

appendvar.bat 스크립트 (어떤 종류의 글로벌 및 지역 APPEND에 대한 보편적 인 구현) : 당신은 대체 할 수

@echo off 

rem Drop last error level 
cd . 

rem Create local variable's stack 
setlocal 

set "?~nx0=%~nx0" 

rem script flags 
rem set variable in global registry for a current user 
set __FLAG_SET_GLOBAL_REGISTRY=0 
rem Set variable in global registry for all users. 
rem Has no meaning if global flag has not used. 
set __FLAG_SET_GLOBAL_REGISTRY_ALL_USERS=0 
rem If setting global variable, then do include changes for a local cmd.exe process environment (by default, it is excluded) 
rem Has no meaning if global flag has not used. 
set __FLAG_SET_LOCAL=0 
rem Force append even if exist. 
set __FLAG_FORCE=0 

:FLAGS_LOOP 

rem flags always at first 
set "__FLAG=%~1" 

if not "%__FLAG%" == ""^
if not "%__FLAG:~0,1%" == "-" set "__FLAG=" 

if not "%__FLAG%" == "" (
    if "%__FLAG%" == "-g" (
    set __FLAG_SET_GLOBAL_REGISTRY=1 
    shift 
) else if "%__FLAG%" == "-all" (
    if %__FLAG_SET_GLOBAL_REGISTRY% NEQ 0 set __FLAG_SET_GLOBAL_REGISTRY_ALL_USERS=1 
    shift 
) else if "%__FLAG%" == "-l" (
    set __FLAG_SET_LOCAL=1 
    shift 
) else if "%__FLAG%" == "-f" (
    set __FLAG_FORCE=1 
    shift 
) else (
    echo.%?~nx0%: error: invalid flag: %__FLAG% 
    exit /b -255 
) >&2 

    rem read until no flags 
    goto FLAGS_LOOP 
) 

if "%~1" == "" (
    echo.%?~nx0%: error: variable name is not set. 
    exit /b 1 
) 

set "__SEPARATOR=" 
if not "%~3" == "" set "__SEPARATOR=%~3" 
if "%__SEPARATOR%" == "" set "__SEPARATOR=;" 
set "__SEPARATOR=%__SEPARATOR:~0,1%" 

set "__NEW_VALUE=%~2" 

rem remove trailing separator character 
if not "%__NEW_VALUE%" == "" (
    if "%__SEPARATOR%" == "%__NEW_VALUE:~-1%" (
    set "__NEW_VALUE=%__NEW_VALUE:~0,-1%" 
) 
) 

rem remove trailing "\" character 
if not "%__NEW_VALUE%" == "" (
    if "\" == "%__NEW_VALUE:~-1%" (
    set "__NEW_VALUE=%__NEW_VALUE:~0,-1%" 
) 
) 

if "%__NEW_VALUE%" == "" (
    if "%~2" == "" exit /b 0 
    rem the variable value is a separator character only 
    exit /b 2 
) 

rem set local at least 
if %__FLAG_SET_GLOBAL_REGISTRY%%__FLAG_SET_LOCAL% EQU 0 set __FLAG_SET_LOCAL=1 
if %__FLAG_SET_GLOBAL_REGISTRY% EQU 0 goto SET_GLOBAL_END 

rem global setup 
set "__VAR_VALUE=" 

if %__FLAG_SET_GLOBAL_REGISTRY_ALL_USERS% NEQ 0 (
    set __FLAG_SET_GLOBAL_REGISTRY_WMIC_WHERE_EXP=where "Name='Path' and UserName='<SYSTEM>'" 
) else (
    set __FLAG_SET_GLOBAL_REGISTRY_WMIC_WHERE_EXP=where "Name='Path' and UserName!='<SYSTEM>'" 
) 

for /F "usebackq eol= tokens=1,* delims==" %%i in (`wmic environment %__FLAG_SET_GLOBAL_REGISTRY_WMIC_WHERE_EXP% get VariableValue /VALUE 2^>NUL`) do if "%%i" == "VariableValue" set "__VAR_VALUE=%%j" 

if not "%__VAR_VALUE%" == "" (
    if "%__SEPARATOR%" == "%__VAR_VALUE:~-1%" (
    set "__VAR_VALUE=%__VAR_VALUE:~0,-1%" 
) 
) 

rem check on existance 
if %__FLAG_FORCE% NEQ 0 goto SET_GLOBAL_IMPL 
if "%__VAR_VALUE%" == "" goto SET_GLOBAL_IMPL 

set "__VAR_VALUE_TMP=%__SEPARATOR%%__VAR_VALUE%%__SEPARATOR%" 

call set "__VAR_VALUE_TMP_EXCLUDED=%%__VAR_VALUE_TMP:%__SEPARATOR%%__NEW_VALUE%%__SEPARATOR%=%%" 

if /i not "%__VAR_VALUE_TMP_EXCLUDED%" == "%__VAR_VALUE_TMP%" goto SET_GLOBAL_END 

:SET_GLOBAL_IMPL 
if not "%__VAR_VALUE%" == "" (
    wmic environment %__FLAG_SET_GLOBAL_REGISTRY_WMIC_WHERE_EXP% set VariableValue="%__VAR_VALUE%%__SEPARATOR%%__NEW_VALUE%" 
) else (
    wmic environment %__FLAG_SET_GLOBAL_REGISTRY_WMIC_WHERE_EXP% set VariableValue="%__NEW_VALUE%" 
) 

:SET_GLOBAL_END 
if %__FLAG_SET_LOCAL% EQU 0 exit /b 

rem local setup 
call set "__VAR_VALUE=%%%~1%%" 

if not "%__VAR_VALUE%" == "" (
    if "%__SEPARATOR%" == "%__VAR_VALUE:~-1%" (
    set "__VAR_VALUE=%__VAR_VALUE:~0,-1%" 
) 
) 

rem check on existance 
if %__FLAG_FORCE% NEQ 0 goto SET_LOCAL_IMPL 
if "%__VAR_VALUE%" == "" goto SET_LOCAL_IMPL 

set "__VAR_VALUE_TMP=%__SEPARATOR%%__VAR_VALUE%%__SEPARATOR%" 

call set "__VAR_VALUE_TMP_EXCLUDED=%%__VAR_VALUE_TMP:%__SEPARATOR%%__NEW_VALUE%%__SEPARATOR%=%%" 

if /i not "%__VAR_VALUE_TMP_EXCLUDED%" == "%__VAR_VALUE_TMP%" goto SET_LOCAL_END 

:SET_LOCAL_IMPL 
if not "%__VAR_VALUE%" == "" (
    endlocal 
    set "%~1=%__VAR_VALUE%%__SEPARATOR%%__NEW_VALUE%" 
) else (
    endlocal 
    set "%~1=%__NEW_VALUE%" 
) 

:SET_LOCAL_END 

exit /b 0 

%__VAR_VALUE%%__SEPARATOR%%__NEW_VALUE% 

~

%__NEW_VALUE%%__SEPARATOR%%__VAR_VALUE% 

변수 값 앞에 추가하려는 경우.

참고 : 스크립트는 문제가 있습니다 (테스트)

  • 변수를 이상 1024 자를 업데이트 할 경우 무시하지만와 비교

    • 값을하지 이상 4096 자 이하 나는 생각한다 (테스트하지)
    • -g 및 -all 플래그가 사용되면 cmd.exe 프로세스가 관리자 권한으로 실행되어야합니다.
  • 0

    UPDATE 다음 RegAddPathToVar 함수의 최신 버전은 여기 : https://sf.net/p/nsisplus (전체 시험 예 : https://sf.net/p/nsisplus/NsisSetupLib/HEAD/tree/trunk/tests/test_RegAddRemovePathGUI/main.nsi)

    여기

    는 NSIS 3.0 전체 및 직접 구현 예이다.

    3 개의 파일로 구성됩니다.

    경우 build.bat - 스크립트 파일을 작성합니다.

    @echo off 
    
    set "MAKENSIS_EXE=makensis.exe" 
    
    "%MAKENSIS_EXE%" /V4 "/Obuild.log" "/XOutFile '%~dp0test.exe'" "%~dp0main.nsi" 
    
    echo.Return code: %ERRORLEVEL% 
    
    pause 
    

    편집에 거기 MAKENSIS_EXE 변수는 makensis 실행 파일 시스템에 있습니다.

    stack.nsi - 헬퍼 함수 파일.

    !define PushStack11 "!insertmacro PushStack11" 
    !macro PushStack11 var0 var1 var2 var3 var4 var5 var6 var7 var8 var9 var10 
    Push `${var0}` 
    Push `${var1}` 
    Push `${var2}` 
    Push `${var3}` 
    Push `${var4}` 
    Push `${var5}` 
    Push `${var6}` 
    Push `${var7}` 
    Push `${var8}` 
    Push `${var9}` 
    Push `${var10}` 
    !macroend 
    
    !define ExchStack4 "!insertmacro ExchStack4" 
    !macro ExchStack4 var0 var1 var2 var3 
    Exch `${var3}` 
    Exch 1 
    Exch `${var2}` 
    Exch 1 
    Exch 2 
    Exch `${var1}` 
    Exch 2 
    Exch 3 
    Exch `${var0}` 
    Exch 3 
    !macroend 
    
    !define PopStack15 "!insertmacro PopStack15" 
    !macro PopStack15 var0 var1 var2 var3 var4 var5 var6 var7 var8 var9 var10 var11 var12 var13 var14 
    Pop `${var14}` 
    Pop `${var13}` 
    Pop `${var12}` 
    Pop `${var11}` 
    Pop `${var10}` 
    Pop `${var9}` 
    Pop `${var8}` 
    Pop `${var7}` 
    Pop `${var6}` 
    Pop `${var5}` 
    Pop `${var4}` 
    Pop `${var3}` 
    Pop `${var2}` 
    Pop `${var1}` 
    Pop `${var0}` 
    !macroend 
    

    main.nsi - 전체 NSIS 구현 예.

    !include "nsDialogs.nsh" 
    !include "WinCore.nsh" 
    !include "LogicLib.nsh" 
    !include "stack.nsi" 
    
    RequestExecutionLevel admin ; for all users 
    
    Page Custom Show Leave 
    
    Var /GLOBAL DialogID 
    Var /GLOBAL EditID 
    Var /GLOBAL Edit 
    Var /GLOBAL ButtonAppendID 
    
    !define GotoIf "!insertmacro GotoIf" 
    !macro GotoIf label exp 
    ${If} ${exp} 
        Goto `${label}` 
    ${EndIf} 
    !macroend 
    
    !define RegGetKeyMap "!insertmacro RegGetKeyMap" 
    !macro RegGetKeyMap var value 
        ${Switch} ${value} 
        ${Case} "HKCR" 
         StrCpy ${var} ${HKEY_CLASSES_ROOT} 
        ${Break} 
        ${Case} "HKCU" 
         StrCpy ${var} ${HKEY_CURRENT_USER} 
        ${Break} 
        ${Case} "HKLM" 
         StrCpy ${var} ${HKEY_LOCAL_MACHINE} 
        ${Break} 
        ${Case} "HKU" 
         StrCpy ${var} ${HKEY_USERS} 
        ${Break} 
        ${Case} "HKPD" 
         StrCpy ${var} ${HKEY_PERFORMANCE_DATA} 
        ${Break} 
        ${Case} "HKDD" 
         StrCpy ${var} ${HKEY_DYN_DATA} 
        ${Break} 
        ${Case} "HKCC" 
         StrCpy ${var} ${HKEY_CURRENT_CONFIG} 
        ${Break} 
        ${Case} "HKEY_CLASSES_ROOT" 
         StrCpy ${var} ${HKEY_CLASSES_ROOT} 
        ${Break} 
        ${Case} "HKEY_CURRENT_USER" 
         StrCpy ${var} ${HKEY_CURRENT_USER} 
        ${Break} 
        ${Case} "HKEY_LOCAL_MACHINE" 
         StrCpy ${var} ${HKEY_LOCAL_MACHINE} 
        ${Break} 
        ${Case} "HKEY_USERS" 
         StrCpy ${var} ${HKEY_USERS} 
        ${Break} 
        ${Case} "HKEY_PERFORMANCE_DATA" 
         StrCpy ${var} ${HKEY_PERFORMANCE_DATA} 
        ${Break} 
        ${Case} "HKEY_DYN_DATA" 
         StrCpy ${var} ${HKEY_DYN_DATA} 
        ${Break} 
        ${Case} "HKEY_CURRENT_CONFIG" 
         StrCpy ${var} ${HKEY_CURRENT_CONFIG} 
        ${Break} 
        ${Default} 
         StrCpy ${var} ${HKEY_CURRENT_USER} 
        ${Break} 
        ${EndSwitch} 
    !macroend 
    
    ; Usage: 
    ; All users: 
    ; ${Push} "<path>" 
    ; ${Push} "HKLM" 
    ; ${Push} "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" 
    ; ${Push} "<env_var>" 
    ; Call RegAddPathToVar 
    ; Current user only: 
    ; ${Push} "<path>" 
    ; ${Push} "HKCU" 
    ; ${Push} "Environment" 
    ; ${Push} "<env_var>" 
    ; Call RegAddPathToVar 
    !macro Func_RegAddPathToVar un 
    !ifndef ${un}RegAddPathToVar_INCLUDED 
    !define ${un}RegAddPathToVar_INCLUDED 
    Function ${un}RegAddPathToVar 
        ${ExchStack4} $R0 $R1 $R2 $R3 
    
        ${PushStack11} $R4 $R5 $R6 $R7 $R8 $R9 $0 $1 $2 $8 $9 
    
        ; WARNING: 
        ; NSIS ReadRegStr returns empty string on string overflow, so native calls are used here: 
        ; 1. To check actual length of <env_var>. 
        ; 2. To process the PATH variable of any length long. 
    
        ; The IDEAL algorithm for any length long PATH variable, where each subpath is not longer than ${NSIS_MAX_STRLEN}-${NSIS_CHAR_SIZE} bytes: 
        ; 1. Init current string list if does not have any before or take as current has created after the previous algorithm run. 
        ; 2. Read string of ${NSIS_MAX_STRLEN}-${NSIS_CHAR_SIZE} bytes length into the array of ${NSIS_MAX_STRLEN} bytes length from the input address, add NSIS_CHAR_SIZE nulls at the end. 
        ; 3. Go to 20 if empty or nothing else except the ; characters in the array. 
        ; 4. Truncate all in the array after the last ; character, where the ; character has found not under " character quoted string (see description in the 6). 
        ; 5. Split strings in the array by the ; character if it has found not under " character quoted string into the list. 
        ; 6. Move the last string from the list into the next repeat cycle list if it begins by the " character but not ends by the same character (not completely fitted into the limited to ${NSIS_MAX_STRLEN} bytes window). 
        ; 7. Unquote all strings in the list and create the second list with flags marked where the quotes has removed. 
        ; 8. Search for "$R0" or "$R0\" in the list, if found then raise a flag and leave the algorithm. 
        ; 9. Move ${NSIS_MAX_STRLEN} byte window by the array current string length long multiple to NSIS_CHAR_SIZE value along the input address. 
        ; 10. Repeat the algorithm. 
        ; 20. Append path to the list. 
        ; 21. Restore quotes for those strings in the first list what been quoted before by the second list. 
        ; 22. Join first list by the separator into one string. 
    
        ; The REAL algorithm for any length long PATH variable, where each subpath is not longer than ${NSIS_MAX_STRLEN}-${NSIS_CHAR_SIZE} bytes: 
        ; 1. Read string from registry into dynamic buffer enough to store more characters: length of being searched string + length of separator + length of string to search + length of null character. 
        ; 2. Copy string from the buffer to the second dynamic buffer enough to store more characters: length of separator + length of being searched string + length of separator + length of null character. 
        ; 3. Prepend and append separator character to second buffer. 
        ; 4. Try to find multiple instances of the string to search in the second buffer through the shlwapi::StrStrI, where search instances are: 
        ;  `<Separator><StringToSearch><Separator>' 
        ;  `<Separator><StringToSearch>\<Separator>' 
        ; 5. If found any instance then leave the algorithm. 
        ; 6. Append separator character to the first buffer if it does not ending by it. 
        ; 7. Append the string to search to the first buffer. 
    
        ; handles and pointers init 
        StrCpy $R7 0 
        StrCpy $R9 0 
        StrCpy $0 0 
        StrCpy $1 0 
        StrCpy $2 0 
    
        ; keys map 
        ${RegGetKeyMap} $R8 $R1 
    
        System::Call "advapi32::RegOpenKey(i R8, t R2, *i.R6) i.R4" 
        ${If} $R4 <> 0 
        DetailPrint "RegAddPathToVar: advapi32::RegOpenKey error: code=$R4 hive=$\"$R8$\" key=$\"$R2$\"" 
        MessageBox MB_OK "RegAddPathToVar: advapi32::RegOpenKey error: code=$R4 hive=$\"$R8$\" key=$\"$R2$\"" /SD IDOK 
        Goto done 
        ${EndIf} 
    
        System::Call "advapi32::RegQueryValueEx(i R6, t R3, i 0, *i .r9, p 0, *i 0 R7) i.R4" 
        ${If} $R4 <> 0 
        DetailPrint "RegAddPathToVar: advapi32::RegQueryValueEx (1) is failed, unexpected error code: code=$R4 length=$\"$R7$\"" 
        MessageBox MB_OK "RegAddPathToVar: advapi32::RegQueryValueEx (1) is failed, unexpected error code: code=$R4 length=$\"$R7$\"" /SD IDOK 
        Goto done 
        ${EndIf} 
    
        ; remove trailing "\" character from the string to search 
        StrCpy $R5 $R0 "" -1 
        ${If} $R5 == "\" 
        StrCpy $R0 $R0 -1 
        ${EndIf} 
    
        StrLen $R8 $R0 
        ; first buffer: length of being searched string + length of separator + length of string to search + length of null character 
        IntOp $R5 $R8 + 1 ; ";" 
        IntOp $R5 $R5 * ${NSIS_CHAR_SIZE} 
        IntOp $R5 $R5 + $R7 ; already in bytes including null character 
    
        ; allocate first dynamic buffer 
        System::Alloc $R5 
        Pop $0 
        ${If} $0 = 0 
        DetailPrint "RegAddPathToVar: System::Alloc (1) is failed: size=$R5" 
        MessageBox MB_OK "RegAddPathToVar: System::Alloc (1) is failed: size=$R5" /SD IDOK 
        Goto done 
        ${EndIf} 
    
        System::Call "advapi32::RegQueryValueEx(i R6, t R3, i 0, i 0, p r0, *i R5 R7) i.R4" 
        ${If} $R4 <> 0 
        DetailPrint "RegAddPathToVar: advapi32::RegQueryValueEx (2) is failed, unexpected error: code=$R4 length=$\"$R7$\"" 
        MessageBox MB_OK "RegAddPathToVar: advapi32::RegQueryValueEx (2) is failed, unexpected error: code=$R4 length=$\"$R7$\"" /SD IDOK 
        Goto done 
        ${EndIf} 
    
        ; strip separator characters from the first buffer end 
        ${If} $R7 > ${NSIS_CHAR_SIZE} 
        ; excluding null character 
        IntOp $R5 $R7 - ${NSIS_CHAR_SIZE} 
        IntOp $R5 $R5 - ${NSIS_CHAR_SIZE} 
        IntOp $R9 $0 + $R5 
    strip_loop1: 
        System::Call "*$R9(&t1 .r8)" 
        ${If} $8 == ";" 
         System::Call "*$R9(&t1 '')" ; null character 
         IntOp $R7 $R7 - ${NSIS_CHAR_SIZE} 
         ${If} $R9 >= ${NSIS_CHAR_SIZE} 
         IntOp $R9 $R9 - ${NSIS_CHAR_SIZE} 
         Goto strip_loop1 
         ${EndIf} 
        ${EndIf} 
        ${EndIf} 
    
        ; second buffer: length of separator + length of being searched string + length of separator + length of null character 
        IntOp $R5 2 * ${NSIS_CHAR_SIZE} ; 2 x ";" 
        IntOp $R5 $R5 + $R7 ; already in bytes including null character 
    
        ; allocate second dynamic buffer 
        System::Alloc $R5 
        Pop $1 
        ${If} $1 = 0 
        DetailPrint "RegAddPathToVar: System::Alloc (2) is failed: size=$R5" 
        MessageBox MB_OK "RegAddPathToVar: System::Alloc (2) is failed: size=$R5" /SD IDOK 
        Goto done 
        ${EndIf} 
    
        System::Call "*$1(&t1 ';')" 
    
        IntOp $R9 $1 + ${NSIS_CHAR_SIZE} 
        System::Call "kernel32::lstrcpyn(p R9, p r0, i R7) p.R4" 
        ${If} $R4 = 0 
        DetailPrint "RegAddPathToVar: kernel32::lstrcpyn (1) is failed" 
        MessageBox MB_OK "RegAddPathToVar: kernel32::lstrcpyn (1) is failed" /SD IDOK 
        Goto done 
        ${EndIf} 
    
        IntOp $R9 $R9 + $R7 
        IntOp $R9 $R9 - ${NSIS_CHAR_SIZE} ; exclude last null character 
        System::Call "*$R9(&t1 ';')" 
        IntOp $R9 $R9 + ${NSIS_CHAR_SIZE} 
        System::Call "*$R9(&t1 '')" ; null character 
    
        ; buffer for the string to search 
        IntOp $R5 0 + 4 ; 2 x ";" + "\" + length of null character 
        IntOp $R5 $R5 + $R8 ; excluding null character 
        IntOp $R5 $R5 * ${NSIS_CHAR_SIZE} 
    
        System::Alloc $R5 
        Pop $2 
        ${If} $2 = 0 
        DetailPrint "RegAddPathToVar: System::Alloc (3) is failed: size=$R5" 
        MessageBox MB_OK "RegAddPathToVar: System::Alloc (3) is failed: size=$R5" /SD IDOK 
        Goto done 
        ${EndIf} 
    
        ; convert R8 (length of R0) to bytes 
        IntOp $R8 $R8 * ${NSIS_CHAR_SIZE} 
    
        ; `<Separator><StringToSearch><Separator>' 
        System::Call "*$2(&t1 ';')" 
    
        IntOp $R9 $2 + ${NSIS_CHAR_SIZE} 
        System::Call "kernel32::lstrcpy(p R9, t R0) p.R4" 
        ${If} $R4 = 0 
        DetailPrint "RegAddPathToVar: kernel32::lstrcpy (2) is failed" 
        MessageBox MB_OK "RegAddPathToVar: kernel32::lstrcpy (2) is failed" /SD IDOK 
        Goto done 
        ${EndIf} 
    
        IntOp $R9 $R9 + $R8 ; length does not include the last null character 
        System::Call "*$R9(&t1 ';')" 
        IntOp $R9 $R9 + ${NSIS_CHAR_SIZE} 
        System::Call "*$R9(&t1 '')" ; null character 
    
        System::Call "shlwapi::StrStrI(p r1, p r2) p.R4" 
        ${GotoIf} done "$R4 <> 0" 
    
        ; `<Separator><StringToSearch>\<Separator>' 
        System::Call "*$2(&t1 ';')" 
    
        IntOp $R9 $2 + ${NSIS_CHAR_SIZE} 
        IntOp $R9 $R9 + $R8 
        System::Call "*$R9(&t1 '\')" 
        IntOp $R9 $R9 + ${NSIS_CHAR_SIZE} 
        System::Call "*$R9(&t1 ';')" 
        IntOp $R9 $R9 + ${NSIS_CHAR_SIZE} 
        System::Call "*$R9(&t1 '')" ; null character 
    
        System::Call "shlwapi::StrStrI(p r1, p r2) p.R4" 
        ${GotoIf} done "$R4 <> 0" 
    
        ; append to the first buffer 
        IntOp $R9 0 + $0 
        ${If} $R7 > ${NSIS_CHAR_SIZE} 
        IntOp $R9 $R9 + $R7 
        IntOp $R9 $R9 - ${NSIS_CHAR_SIZE} ; exclude last null character 
        System::Call "*$R9(&t1 ';')" 
        IntOp $R9 $R9 + ${NSIS_CHAR_SIZE} 
        ${EndIf} 
    
        System::Call "kernel32::lstrcpy(p R9, t R0) p.R4" 
        ${If} $R4 = 0 
        DetailPrint "RegAddPathToVar: kernel32::lstrcpy (3) is failed" 
        MessageBox MB_OK "RegAddPathToVar: kernel32::lstrcpy (3) is failed" /SD IDOK 
        Goto done 
        ${EndIf} 
    
        IntOp $R9 $R9 + $R8 ; length does not include the last null character 
        System::Call "*$R9(&t1 '')" ; null character 
    
        IntOp $R9 $R9 + ${NSIS_CHAR_SIZE} 
        IntOp $R5 $R9 - $0 
    
        System::Call "advapi32::RegSetValueEx(i R6, t R3, i 0, i r9, p r0, i R5) i.R4" 
        ${If} $R4 <> 0 
        DetailPrint "RegAddPathToVar: advapi32::RegSetValueEx (1) is failed" 
        MessageBox MB_OK "RegAddPathToVar: advapi32::RegSetValueEx (1) is failed" /SD IDOK 
        Goto done 
        ${EndIf} 
    
        ; broadcast global event 
        SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 
    
    done: 
        System::Call "advapi32::RegCloseKey(i $R6)" 
    
        ${If} $0 <> 0 
        System::Free $0 
        ${EndIf} 
        ${If} $1 <> 0 
        System::Free $1 
        ${EndIf} 
        ${If} $2 <> 0 
        System::Free $2 
        ${EndIf} 
    
        ${PopStack15} $R0 $R1 $R2 $R3 $R4 $R5 $R6 $R7 $R8 $R9 $0 $1 $2 $8 $9 
    FunctionEnd 
    !endif 
    !macroend 
    
    !define Call_RegAddPathToVar "!insertmacro Call_RegAddPathToVar" 
    !macro Call_RegAddPathToVar prefix path hkey hkey_path env_var 
    Push `${path}` 
    Push `${hkey}` 
    Push `${hkey_path}` 
    Push `${env_var}` 
    Call ${prefix}RegAddPathToVar 
    !macroend 
    
    !define RegAddPathToVar "!insertmacro RegAddPathToVar" 
    !macro RegAddPathToVar 
    !insertmacro Func_RegAddPathToVar "" 
    !undef RegAddPathToVar 
    !define RegAddPathToVar "${Call_RegAddPathToVar} ''" 
    !macroend 
    
    !define un.RegAddPathToVar "!insertmacro un.RegAddPathToVar" 
    !macro un.RegAddPathToVar 
    !insertmacro Func_RegAddPathToVar "un." 
    !undef un.RegAddPathToVar 
    !define un.RegAddPathToVar "${Call_RegAddPathToVar} 'un.'" 
    !macroend 
    
    ; include for install only 
    ${RegAddPathToVar} 
    
    Function Show 
        nsDialogs::Create 1018 
        Pop $DialogID 
    
        ${NSD_CreateText} 0 16u 80% 14u "C:\MyPath\bin" 
        Pop $EditID 
    
        ${NSD_OnChange} $EditID WndProc 
    
        ${NSD_CreateButton} 80% 16u 20% 14u "Append" 
        Pop $ButtonAppendID 
    
        ${NSD_OnClick} $ButtonAppendID WndProc 
    
        StrCpy $R0 -1 
        Call Update 
    
        nsDialogs::Show 
    FunctionEnd 
    
    Function Leave 
    FunctionEnd 
    
    Function WndProc 
        System::Store SR0 
        Call Update 
        System::Store L 
    FunctionEnd 
    
    Function Update 
        ; read values 
        ${If} $R0 = $EditID 
        ${OrIf} $R0 = -1 
        ${NSD_GetText} $EditID $Edit 
        ${EndIf} 
        ${If} $R0 = $ButtonAppendID 
        ${If} $Edit != "" 
         #${RegAddPathToVar} "$Edit" HKCU "Environment" PATH ; for current user 
         ${RegAddPathToVar} "$Edit" HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" PATH ; for all users 
        ${EndIf} 
        ${EndIf} 
    FunctionEnd 
    
    Section -Hidden 
    SectionEnd 
    
    관련 문제