Original work on these goes to Klonk and his Portable Application Template. I use a modified version of that great piece of work all the time for apps. I wanted to bring those functions over to be used with any other apps, as they're great for working with backup/restore of multiple registry keys.
These are modified versions of his original functions from v2.2 of his template. I hope they're useful for others as well.
Notes: You need the Registry plugin. Copy and paste into 'SomeName.nsh' In you main script add -
!include SomeName.nsh
All !define statements are also made in your main NSIS script. It will automatically include 'Registry.nsh' and 'WordFunc.nsh'
/*************************************************************************** Copyright 2007 Karl Loncarek Copyright 2007-2008 wraithdu USAGE: REQUIRED - Registry plugin insert regkeys to use separated by "||" !define REGKEYS "HKLM\SOFTWARE\Microsoft\etc||HKCU\Second\Key" name of app for backup keys !define APPNAME "name of app" skip saving reg keys to file on close !define NOSAVE Call InitReg Call CleanReg ***************************************************************************/ !include Registry.nsh !include WordFunc.nsh !insertmacro WordFind ; ************************************************************************** ; * Function: Backup registry keys, apply portable registry keys ; ************************************************************************** Function InitReg StrCpy $R8 "0" ; reset variable StrCpy $R0 "${REGKEYS}" ; copy constant to working variable Call ValuesToStack ; separate values from REGKEYS to stack InitRegLoop: Pop $R9 ; obtain registry key from stack StrCmp $R9 "EndOfStack" InitRegApply ; do not do registry parsing, when no keys given anymore IntOp $R8 $R8 + 1 ; increase counter ; -------------------------------------------------------------------------- ; Backup registry key ; -------------------------------------------------------------------------- ${registry::KeyExists} "$R9" $R7 ; check whether registry key exists StrCmp $R7 "0" 0 InitRegLoop ; registry key does not exist, do not save anything ${registry::MoveKey} "$R9" "$R9_${APPNAME}-bkup" $R7 ; Rename registry key Goto InitRegLoop InitRegApply: ; -------------------------------------------------------------------------- ; Apply portable registry key ; -------------------------------------------------------------------------- IfFileExists "$EXEDIR\Data\settings\${APPNAME}_portable.reg" 0 InitRegEnd ; only apply if a registry file exists ExecWait 'regedit /s "$EXEDIR\Data\settings\${APPNAME}_portable.reg"' ; Restore saved registry keys InitRegEnd: FunctionEnd ; ************************************************************************** ; * Function: Copy registry key (portable), restore oroginal registry key ; ************************************************************************** Function CleanReg StrCpy $R8 "0" ; reset variable StrCpy $R0 "${REGKEYS}" ; copy constant to working variable Call ValuesToStack ; separate values from REGKEYS to stack IfFileExists "$EXEDIR\Data\settings\*.*" +3 CreateDirectory "$EXEDIR\Data\settings" ; create registry directory if it does not exist Goto CleanRegLoop IfFileExists "$EXEDIR\Data\settings\${APPNAME}_portable.reg" 0 +2 Delete "$EXEDIR\Data\settings\${APPNAME}_portable.reg" ; delete portable registry file if it exists to write a new one CleanRegLoop: Pop $R9 ; obtain registry key from stack StrCmp $R9 "EndOfStack" CleanRegEnd ; do not do registry parsing, when no keys given anymore IntOp $R8 $R8 + 1 ; increase counter ; -------------------------------------------------------------------------- ; Copy actual registry key to portable folder ; -------------------------------------------------------------------------- ${registry::KeyExists} "$R9" $R7 ; check whether registry key exists StrCmp $R7 "0" 0 CleanRegRename ; registry key does not exist, do not save anything !ifndef NOSAVE ${registry::SaveKey} "$R9" "$EXEDIR\Data\settings\${APPNAME}_portable.reg" "/G=1 /A=1" $R7 ; Backup registry key !endif ; -------------------------------------------------------------------------- ; Delete actual actual registry key (with portable content) ; -------------------------------------------------------------------------- ${registry::DeleteKey} "$R9" $R7 ; Delete registry key ; -------------------------------------------------------------------------- ; Restore original registry key if backup exists ; -------------------------------------------------------------------------- CleanRegRename: ${registry::KeyExists} "$R9_${APPNAME}-bkup" $R7 StrCmp $R7 "0" 0 CleanRegLoop ; only rename if a backup key exists ${registry::MoveKey} "$R9_${APPNAME}-bkup" "$R9" $R7 ; Rename backup registry key Goto CleanRegLoop CleanRegEnd: FunctionEnd ; ************************************************************************** ; * Helper Function: Move value of constants onto stack, $R0 holds values separated by "||" ; ************************************************************************** Function ValuesToStack StrCpy $0 "0" ; reset counter ; -------------------------------------------------------------------------- ; Get single parameter out of list, i.e. obtain next single registry key ; -------------------------------------------------------------------------- Push "EndOfStack" ; set end marker for stack ValuesToStackStart: StrCmp $R0 "" ValuesToStackEnd ; do not do registry parsing, when no keys given anymore IntOp $0 $0 + 1 ; increase counter ${WordFind} "$R0" "||" "-01" $9 ; save last parameter to register ${WordFind} "$R0" "||" "-02{*" $R0 ; remove last part from saved value Push $9 ; save parameter to stack StrCmp $R0 $9 ValuesToStackEnd ; if values are identical (last parameter) -> no more delimiters Goto ValuesToStackStart ValuesToStackEnd: FunctionEnd