You are here

Registry Backup/Restore Functions

1 post / 0 new
wraithdu
Offline
Last seen: 10 years 10 months ago
Developer
Joined: 2007-06-27 20:22
Registry Backup/Restore Functions

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