Uninstall only installed files: Difference between revisions
Rapitharian (talk | contribs) m (→Description) |
KennZAney1 (talk | contribs) |
||
(28 intermediate revisions by 9 users not shown) | |||
Line 4: | Line 4: | ||
This code was written for [[User:Rookie12|Rookie12]] a long while back. So many people have asked the same question since, so I thought that it was a good idea to put it up on here. | This code was written for [[User:Rookie12|Rookie12]] a long while back. So many people have asked the same question since, so I thought that it was a good idea to put it up on here. | ||
---- | |||
'''Macros updated 26th February 2013''' | |||
*Added the RestoreFiles macro. | |||
This Macro is used when restoring files using the information found in an uninstall log. The RestoreFile Macro does not function for this purpose (Seems to be an issue with the Rename function.) As a result I created this one with the Copy Function. This macro also only uses 2 variables vs three for RestoreFile. | |||
-Rapitharian | |||
---- | |||
'''Macros updated 24th February 2013''' | |||
*Added the BackupFiles macro. | |||
This Macro is used when backing up a file before the installer replaces the file. | |||
-Rapitharian | |||
---- | |||
'''Macros updated 23th February 2013''' | |||
*Added BackupFile macro. | |||
*Added RestoreFile macro. | |||
*Fixed a flaw in the "Files" macro. | |||
- The third line of the macro | |||
File "${FilePath}\${FileName}" | |||
was changed to: | |||
File "${FileName}" | |||
-Rapitharian | |||
---- | |||
'''Script updated 7th December 2011''' | |||
*Added WriteIniStr macro. | |||
*Added <pre>RMDir "$INSTDIR"</pre> after <pre>Delete "$INSTDIR\${UninstLog}"</pre> because previous log entries will fail the remove because of the presence the log file. | |||
-Cjenkins | |||
---- | ---- | ||
Line 9: | Line 43: | ||
'''Entire script updated 20th October 2010''' | '''Entire script updated 20th October 2010''' | ||
*Added macros for WriteRegStr and WriteRegDWORD. | *Added macros for WriteRegStr and WriteRegDWORD. | ||
*The script can now process the addition and removal of registry values as well as files. | |||
*Added StrCmp, to the uninstaller code, to determine if the item is a Registry Value. | *Added StrCmp, to the uninstaller code, to determine if the item is a Registry Value. | ||
*Broke the code into a macro file added to the main script via an !include | *Broke the code into a macro file; added to the main script via an !include, this should help keep your scripts clean and allow reuse of the macros. | ||
-Rapitharian | -Rapitharian | ||
---- | ---- | ||
Line 61: | Line 93: | ||
== The Macro Script == | == The Macro Script == | ||
Take the next chunk of code and save it to a file called <code>UnInstallLog.nsh</code> in <code>%ProgramFiles%\NSIS\Include\</code>. | |||
<highlight-nsis> | <highlight-nsis> | ||
Line 70: | Line 102: | ||
;File macro | ;File macro | ||
!macro File | !macro File FileName | ||
IfFileExists "$OUTDIR\${FileName}" +2 | IfFileExists "$OUTDIR\${FileName}" +2 | ||
FileWrite $UninstLog "$OUTDIR\${FileName}$\r$\n" | FileWrite $UninstLog "$OUTDIR\${FileName}$\r$\n" | ||
File " | File "${FileName}" | ||
!macroend | !macroend | ||
; | ;CreateShortCut macro | ||
!macro | !macro CreateShortCut FilePath FilePointer Pamameters Icon IconIndex | ||
FileWrite $UninstLog "${FilePath}$\r$\n" | FileWrite $UninstLog "${FilePath}$\r$\n" | ||
CreateShortCut "${FilePath}" "${FilePointer}" "${Pamameters}" "${Icon}" "${IconIndex}" | |||
!macroend | !macroend | ||
Line 112: | Line 144: | ||
WriteUninstaller "${Path}" | WriteUninstaller "${Path}" | ||
FileWrite $UninstLog "${Path}$\r$\n" | FileWrite $UninstLog "${Path}$\r$\n" | ||
!macroend | |||
;WriteIniStr macro | |||
!macro WriteIniStr IniFile SectionName EntryName NewValue | |||
IfFileExists "${IniFile}" +2 | |||
FileWrite $UninstLog "${IniFile}$\r$\n" | |||
WriteIniStr "${IniFile}" "${SectionName}" "${EntryName}" "${NewValue}" | |||
!macroend | !macroend | ||
Line 124: | Line 163: | ||
!macro WriteRegDWORD RegRoot UnInstallPath Key Value | !macro WriteRegDWORD RegRoot UnInstallPath Key Value | ||
FileWrite $UninstLog "${RegRoot} ${UnInstallPath}$\r$\n" | FileWrite $UninstLog "${RegRoot} ${UnInstallPath}$\r$\n" | ||
WriteRegDWORD "${RegRoot}" "${UnInstallPath}" "${Key}" "${Value}" | |||
!macroend | |||
;BackupFile macro | |||
!macro BackupFile FILE_DIR FILE BACKUP_TO | |||
IfFileExists "${BACKUP_TO}\*.*" +2 | |||
CreateDirectory "${BACKUP_TO}" | |||
IfFileExists "${FILE_DIR}\${FILE}" 0 +2 | |||
Rename "${FILE_DIR}\${FILE}" "${BACKUP_TO}\${FILE}" | |||
!macroend | |||
;RestoreFile macro | |||
!macro RestoreFile BUP_DIR FILE RESTORE_TO | |||
IfFileExists "${BUP_DIR}\${FILE}" 0 +2 | |||
Rename "${BUP_DIR}\${FILE}" "${RESTORE_TO}\${FILE}" | |||
!macroend | |||
;BackupFiles macro | |||
!macro BackupFiles FILE_DIR FILE BACKUP_TO | |||
IfFileExists "${BACKUP_TO}\*.*" +2 | |||
CreateDirectory "22222" | |||
IfFileExists "${FILE_DIR}\${FILE}" 0 +7 | |||
FileWrite $UninstLog "${FILE_DIR}\${FILE}$\r$\n" | |||
FileWrite $UninstLog "${BACKUP_TO}\${FILE}$\r$\n" | |||
FileWrite $UninstLog "FileBackup$\r$\n" | |||
Rename "${FILE_DIR}\${FILE}" "${BACKUP_TO}\${FILE}" | |||
SetOutPath "${FILE_DIR}" | |||
File "${FILE}" #After the Original file is backed up write the new file. | |||
!macroend | |||
;RestoreFiles macro | |||
!macro RestoreFiles BUP_FILE RESTORE_FILE | |||
IfFileExists "${BUP_FILE}" 0 +2 | |||
CopyFiles "${BUP_FILE}" "${RESTORE_FILE}" | |||
!macroend | !macroend | ||
</highlight-nsis> | </highlight-nsis> | ||
== The Script == | == The Script == | ||
Now add the include to the top of your script: | |||
<highlight-nsis> | <highlight-nsis> | ||
!include "UninstallLog.nsh" | !include "UninstallLog.nsh" | ||
<highlight-nsis> | </highlight-nsis> | ||
'''The next chunk of code goes before all your sections, in your script…''' | |||
<highlight-nsis> | <highlight-nsis> | ||
Line 143: | Line 216: | ||
!define UninstLog "uninstall.log" | !define UninstLog "uninstall.log" | ||
Var UninstLog | Var UninstLog | ||
;The root registry to write to | |||
!define REG_ROOT "HKLM" | |||
;The registry path to write to | |||
!define REG_APP_PATH "SOFTWARE\appname" | |||
;Uninstall log file missing. | ;Uninstall log file missing. | ||
Line 149: | Line 226: | ||
;AddItem macro | ;AddItem macro | ||
!define AddItem "!insertmacro AddItem" | !define AddItem "!insertmacro AddItem" | ||
;BackupFile macro | |||
!define BackupFile "!insertmacro BackupFile" | |||
;BackupFiles macro | |||
!define BackupFiles "!insertmacro BackupFiles" | |||
;Copy files macro | |||
!define CopyFiles "!insertmacro CopyFiles" | |||
;CreateDirectory macro | |||
!define CreateDirectory "!insertmacro CreateDirectory" | |||
;CreateShortcut macro | |||
!define CreateShortcut "!insertmacro CreateShortcut" | |||
;File macro | ;File macro | ||
!define File "!insertmacro File" | !define File "!insertmacro File" | ||
;Rename macro | ;Rename macro | ||
!define Rename "!insertmacro Rename" | !define Rename "!insertmacro Rename" | ||
; | ;RestoreFile macro | ||
!define | !define RestoreFile "!insertmacro RestoreFile" | ||
;RestoreFiles macro | |||
!define RestoreFiles "!insertmacro RestoreFiles" | |||
;SetOutPath macro | ;SetOutPath macro | ||
!define SetOutPath "!insertmacro SetOutPath" | !define SetOutPath "!insertmacro SetOutPath" | ||
; | ;WriteRegDWORD macro | ||
!define | !define WriteRegDWORD "!insertmacro WriteRegDWORD" | ||
;WriteRegStr macro | ;WriteRegStr macro | ||
!define WriteRegStr "!insertmacro WriteRegStr" | !define WriteRegStr "!insertmacro WriteRegStr" | ||
; | ;WriteUninstaller macro | ||
!define | !define WriteUninstaller "!insertmacro WriteUninstaller" | ||
Section -openlogfile | Section -openlogfile | ||
CreateDirectory "$INSTDIR" | CreateDirectory "$INSTDIR" | ||
Line 187: | Line 276: | ||
SectionEnd</highlight-nsis> | SectionEnd</highlight-nsis> | ||
Your sections, (the ones that add files,) need to be placed "here" (between the above and below chunks of code) in your script.<br /> | |||
Instead of using | Instead of using [[Reference/File|File]], [[Reference/CreateShortCut|CreateShortCut]], [[Reference/CopyFiles|CopyFiles]], [[Reference/Rename|Rename]], [[Reference/CreateDirectory|CreateDirectory]], [[Reference/SetOutPath|SetOutPath]], [[Reference/WriteUninstaller|WriteUninstaller]], [[Reference/WriteINIStr|WriteINIStr]], [[Reference/WriteRegStr|WriteRegStr]] and [[Reference/WriteRegDWORD|WriteRegDWORD]] instructions in your sections, use <code>${AddItem}</code>, <code>${File}</code>, <code>${CreateShortcut}</code>, <code>${CopyFiles}</code>, <code>${Rename}</code>, <code>${CreateDirectory}</code>, <code>${SetOutPath}</code>, <code>${WriteUninstaller}</code>, <code>${WriteIniStr}</code>, <code>${WriteRegStr}</code> and <code>${WriteRegDWORD}</code> instead.</p> | ||
Please note: when using <code>${SetOutPath}</code> to create more than one upper level directory, e.g.:<br /> | |||
<code>${SetOutPath} "$INSTDIR\dir1\dir2\dir3"</code>, you need to add entries for each lower level directory for them all to be deleted: | |||
<highlight-nsis> | <highlight-nsis> | ||
${AddItem} "$INSTDIR\dir1" | ${AddItem} "$INSTDIR\dir1" | ||
Line 198: | Line 288: | ||
</highlight-nsis> | </highlight-nsis> | ||
'''The Following is an example of what your sections may look like…''' | |||
<highlight-nsis> | <highlight-nsis> | ||
Line 211: | Line 301: | ||
${WriteRegStr} "${REG_ROOT}" "${REG_APP_PATH}" "Install Directory" "$INSTDIR" | ${WriteRegStr} "${REG_ROOT}" "${REG_APP_PATH}" "Install Directory" "$INSTDIR" | ||
;Write the Uninstall information into the registry | ;Write the Uninstall information into the registry | ||
${WriteRegStr} ${REG_ROOT} "${UNINSTALL_PATH}" "UninstallString" | ${WriteRegStr} ${REG_ROOT} "${UNINSTALL_PATH}" "UninstallString" "$INSTDIR\uninstall.exe" | ||
SectionEnd | SectionEnd | ||
Line 229: | Line 319: | ||
</highlight-nsis> | </highlight-nsis> | ||
'''The next chunk of code comes after all of your sections, in your script…''' | |||
<highlight-nsis> | <highlight-nsis> | ||
Line 279: | Line 369: | ||
FileClose $UninstLog | FileClose $UninstLog | ||
Delete "$INSTDIR\${UninstLog}" | Delete "$INSTDIR\${UninstLog}" | ||
RMDir "$INSTDIR" | |||
Pop $R2 | Pop $R2 | ||
Pop $R1 | Pop $R1 |
Latest revision as of 18:56, 16 January 2018
Author: Afrow UK (talk, contrib) |
Description
This code was written for Rookie12 a long while back. So many people have asked the same question since, so I thought that it was a good idea to put it up on here.
Macros updated 26th February 2013
- Added the RestoreFiles macro.
This Macro is used when restoring files using the information found in an uninstall log. The RestoreFile Macro does not function for this purpose (Seems to be an issue with the Rename function.) As a result I created this one with the Copy Function. This macro also only uses 2 variables vs three for RestoreFile.
-Rapitharian
Macros updated 24th February 2013
- Added the BackupFiles macro.
This Macro is used when backing up a file before the installer replaces the file.
-Rapitharian
Macros updated 23th February 2013
- Added BackupFile macro.
- Added RestoreFile macro.
- Fixed a flaw in the "Files" macro.
- The third line of the macro File "${FilePath}\${FileName}" was changed to: File "${FileName}"
-Rapitharian
Script updated 7th December 2011
- Added WriteIniStr macro.
- Added
RMDir "$INSTDIR"
afterDelete "$INSTDIR\${UninstLog}"
because previous log entries will fail the remove because of the presence the log file.
-Cjenkins
Entire script updated 20th October 2010
- Added macros for WriteRegStr and WriteRegDWORD.
- The script can now process the addition and removal of registry values as well as files.
- Added StrCmp, to the uninstaller code, to determine if the item is a Registry Value.
- Broke the code into a macro file; added to the main script via an !include, this should help keep your scripts clean and allow reuse of the macros.
-Rapitharian
Entire script updated 12th May 2006
- Added functions for AddItem, CopyFiles and Rename.
- RMDir /r removed.
- Log file now read in reverse order.
-Stu
Script updated 28 Sep 2006
- Fix issue where uninstall.log is not created if $INSTDIR doesn't already exist
- Fix infinite loop on uninstall - "last" line (actually first line) of uninstall.log is read over and over again
- Anonymoose
Script updated 08 Nov 2006
- Uninstaller now deletes itself and $INSTDIR
- mark
Script updated 27 April 2007
- Removed Delete instruction to delete the uninstaller and added ${WriteUninstaller} instead.
- RMDir $INSDIR was repeated from last update.
- Afrow UK
Script updated 18 August 2009
- Added ${CreateShortcut} macro based on ${File}.
- Adm.Wiggin
Script updated 28 Dec 2009
- Uninstaller now works faster (it needs to parse uninstall.log only one time)
- Aleppin
The Macro Script
Take the next chunk of code and save it to a file called UnInstallLog.nsh
in %ProgramFiles%\NSIS\Include\
.
;AddItem macro !macro AddItem Path FileWrite $UninstLog "${Path}$\r$\n" !macroend ;File macro !macro File FileName IfFileExists "$OUTDIR\${FileName}" +2 FileWrite $UninstLog "$OUTDIR\${FileName}$\r$\n" File "${FileName}" !macroend ;CreateShortCut macro !macro CreateShortCut FilePath FilePointer Pamameters Icon IconIndex FileWrite $UninstLog "${FilePath}$\r$\n" CreateShortCut "${FilePath}" "${FilePointer}" "${Pamameters}" "${Icon}" "${IconIndex}" !macroend ;Copy files macro !macro CopyFiles SourcePath DestPath IfFileExists "${DestPath}" +2 FileWrite $UninstLog "${DestPath}$\r$\n" CopyFiles "${SourcePath}" "${DestPath}" !macroend ;Rename macro !macro Rename SourcePath DestPath IfFileExists "${DestPath}" +2 FileWrite $UninstLog "${DestPath}$\r$\n" Rename "${SourcePath}" "${DestPath}" !macroend ;CreateDirectory macro !macro CreateDirectory Path CreateDirectory "${Path}" FileWrite $UninstLog "${Path}$\r$\n" !macroend ;SetOutPath macro !macro SetOutPath Path SetOutPath "${Path}" FileWrite $UninstLog "${Path}$\r$\n" !macroend ;WriteUninstaller macro !macro WriteUninstaller Path WriteUninstaller "${Path}" FileWrite $UninstLog "${Path}$\r$\n" !macroend ;WriteIniStr macro !macro WriteIniStr IniFile SectionName EntryName NewValue IfFileExists "${IniFile}" +2 FileWrite $UninstLog "${IniFile}$\r$\n" WriteIniStr "${IniFile}" "${SectionName}" "${EntryName}" "${NewValue}" !macroend ;WriteRegStr macro !macro WriteRegStr RegRoot UnInstallPath Key Value FileWrite $UninstLog "${RegRoot} ${UnInstallPath}$\r$\n" WriteRegStr "${RegRoot}" "${UnInstallPath}" "${Key}" "${Value}" !macroend ;WriteRegDWORD macro !macro WriteRegDWORD RegRoot UnInstallPath Key Value FileWrite $UninstLog "${RegRoot} ${UnInstallPath}$\r$\n" WriteRegDWORD "${RegRoot}" "${UnInstallPath}" "${Key}" "${Value}" !macroend ;BackupFile macro !macro BackupFile FILE_DIR FILE BACKUP_TO IfFileExists "${BACKUP_TO}\*.*" +2 CreateDirectory "${BACKUP_TO}" IfFileExists "${FILE_DIR}\${FILE}" 0 +2 Rename "${FILE_DIR}\${FILE}" "${BACKUP_TO}\${FILE}" !macroend ;RestoreFile macro !macro RestoreFile BUP_DIR FILE RESTORE_TO IfFileExists "${BUP_DIR}\${FILE}" 0 +2 Rename "${BUP_DIR}\${FILE}" "${RESTORE_TO}\${FILE}" !macroend ;BackupFiles macro !macro BackupFiles FILE_DIR FILE BACKUP_TO IfFileExists "${BACKUP_TO}\*.*" +2 CreateDirectory "22222" IfFileExists "${FILE_DIR}\${FILE}" 0 +7 FileWrite $UninstLog "${FILE_DIR}\${FILE}$\r$\n" FileWrite $UninstLog "${BACKUP_TO}\${FILE}$\r$\n" FileWrite $UninstLog "FileBackup$\r$\n" Rename "${FILE_DIR}\${FILE}" "${BACKUP_TO}\${FILE}" SetOutPath "${FILE_DIR}" File "${FILE}" #After the Original file is backed up write the new file. !macroend ;RestoreFiles macro !macro RestoreFiles BUP_FILE RESTORE_FILE IfFileExists "${BUP_FILE}" 0 +2 CopyFiles "${BUP_FILE}" "${RESTORE_FILE}" !macroend
The Script
Now add the include to the top of your script:
!include "UninstallLog.nsh"
The next chunk of code goes before all your sections, in your script…
;-------------------------------- ; Configure UnInstall log to only remove what is installed ;-------------------------------- ;Set the name of the uninstall log !define UninstLog "uninstall.log" Var UninstLog ;The root registry to write to !define REG_ROOT "HKLM" ;The registry path to write to !define REG_APP_PATH "SOFTWARE\appname" ;Uninstall log file missing. LangString UninstLogMissing ${LANG_ENGLISH} "${UninstLog} not found!$\r$\nUninstallation cannot proceed!" ;AddItem macro !define AddItem "!insertmacro AddItem" ;BackupFile macro !define BackupFile "!insertmacro BackupFile" ;BackupFiles macro !define BackupFiles "!insertmacro BackupFiles" ;Copy files macro !define CopyFiles "!insertmacro CopyFiles" ;CreateDirectory macro !define CreateDirectory "!insertmacro CreateDirectory" ;CreateShortcut macro !define CreateShortcut "!insertmacro CreateShortcut" ;File macro !define File "!insertmacro File" ;Rename macro !define Rename "!insertmacro Rename" ;RestoreFile macro !define RestoreFile "!insertmacro RestoreFile" ;RestoreFiles macro !define RestoreFiles "!insertmacro RestoreFiles" ;SetOutPath macro !define SetOutPath "!insertmacro SetOutPath" ;WriteRegDWORD macro !define WriteRegDWORD "!insertmacro WriteRegDWORD" ;WriteRegStr macro !define WriteRegStr "!insertmacro WriteRegStr" ;WriteUninstaller macro !define WriteUninstaller "!insertmacro WriteUninstaller" Section -openlogfile CreateDirectory "$INSTDIR" IfFileExists "$INSTDIR\${UninstLog}" +3 FileOpen $UninstLog "$INSTDIR\${UninstLog}" w Goto +4 SetFileAttributes "$INSTDIR\${UninstLog}" NORMAL FileOpen $UninstLog "$INSTDIR\${UninstLog}" a FileSeek $UninstLog 0 END SectionEnd
Your sections, (the ones that add files,) need to be placed "here" (between the above and below chunks of code) in your script.
Instead of using File, CreateShortCut, CopyFiles, Rename, CreateDirectory, SetOutPath, WriteUninstaller, WriteINIStr, WriteRegStr and WriteRegDWORD instructions in your sections, use ${AddItem}
, ${File}
, ${CreateShortcut}
, ${CopyFiles}
, ${Rename}
, ${CreateDirectory}
, ${SetOutPath}
, ${WriteUninstaller}
, ${WriteIniStr}
, ${WriteRegStr}
and ${WriteRegDWORD}
instead.
Please note: when using ${SetOutPath}
to create more than one upper level directory, e.g.:
${SetOutPath} "$INSTDIR\dir1\dir2\dir3"
, you need to add entries for each lower level directory for them all to be deleted:
${AddItem} "$INSTDIR\dir1" ${AddItem} "$INSTDIR\dir1\dir2" ${SetOutPath} "$INSTDIR\dir1\dir2\dir3"
The Following is an example of what your sections may look like…
Section "Install Main" SectionIn RO ${SetOutPath} $INSTDIR ${WriteUninstaller} "uninstall.exe" ${File} "dir1\" "file1.ext" ${File} "dir1\" "file2.ext" ${File} "dir1\" "file3.ext" ;Write the installation path into the registry ${WriteRegStr} "${REG_ROOT}" "${REG_APP_PATH}" "Install Directory" "$INSTDIR" ;Write the Uninstall information into the registry ${WriteRegStr} ${REG_ROOT} "${UNINSTALL_PATH}" "UninstallString" "$INSTDIR\uninstall.exe" SectionEnd Section "Install Other" ${AddItem} "$INSTDIR\Other" ${SetOutPath} "$INSTDIR\Other\Temp" ${File} "dir2\" "file4.ext" ${File} "dir2\" "file5.ext" ${File} "dir2\" "file6.ext" SectionEnd Section "Copy Files & Rename" ${CreateDirectory} "$INSTDIR\backup" ${CopyFiles} "$INSTDIR\file1.ext" "$INSTDIR\backup\file1.ext" ${Rename} "$INSTDIR\file2.ext" "$INSTDIR\file1.ext" SectionEnd
The next chunk of code comes after all of your sections, in your script…
;-------------------------------- ; Uninstaller ;-------------------------------- Section Uninstall ;Can't uninstall if uninstall log is missing! IfFileExists "$INSTDIR\${UninstLog}" +3 MessageBox MB_OK|MB_ICONSTOP "$(UninstLogMissing)" Abort Push $R0 Push $R1 Push $R2 SetFileAttributes "$INSTDIR\${UninstLog}" NORMAL FileOpen $UninstLog "$INSTDIR\${UninstLog}" r StrCpy $R1 -1 GetLineCount: ClearErrors FileRead $UninstLog $R0 IntOp $R1 $R1 + 1 StrCpy $R0 $R0 -2 Push $R0 IfErrors 0 GetLineCount Pop $R0 LoopRead: StrCmp $R1 0 LoopDone Pop $R0 IfFileExists "$R0\*.*" 0 +3 RMDir $R0 #is dir Goto +9 IfFileExists $R0 0 +3 Delete $R0 #is file Goto +6 StrCmp $R0 "${REG_ROOT} ${REG_APP_PATH}" 0 +3 DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}" #is Reg Element Goto +3 StrCmp $R0 "${REG_ROOT} ${UNINSTALL_PATH}" 0 +2 DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}" #is Reg Element IntOp $R1 $R1 - 1 Goto LoopRead LoopDone: FileClose $UninstLog Delete "$INSTDIR\${UninstLog}" RMDir "$INSTDIR" Pop $R2 Pop $R1 Pop $R0 ;Remove registry keys ;DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}" ;DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}" SectionEnd
-Rapitharian