Auto-uninstall old before installing new: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
No edit summary
(Empty string protection)
 
(6 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{PageAuthor|codehistorian}}
{{PageAuthor|Anders}}
[[Category:Code Examples]]
[[Category:Functions_%26_Macros]]


This is a code snippet you can put into your .onInit function that will detect whether your software is already installed and, if so, allows the user to uninstall it first.
This code can be used to uninstall a existing installation. The previous installation must also be a NSIS based install.
 
In the source below, we use the define ${PROGRAM_NAME} to be the name of the product as well as the name of the installer/uninstaller.  You can either define this define or search/replace it. If you name your uninstaller or registry location differently, you should change those strings accordingly.


<highlight-nsis>
<highlight-nsis>
Function .onInit
RequestExecutionLevel User
InstallDir "$LocalAppData\Programs\NSISTest"
!define UninstId "NSISTest" ; You might want to use a GUID here


  ReadRegStr $R0 HKLM \
!include LogicLib.nsh
  "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" \
  "UninstallString"
  StrCmp $R0 "" done


  MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
  "${PROGRAM_NAME} is already installed. $\n$\nClick `OK` to remove the \
  previous version or `Cancel` to cancel this upgrade." \
  IDOK uninst
  Abort
 
;Run the uninstaller
uninst:
  ClearErrors
  ; Copy the uninstaller to a temp location
  GetTempFileName $0
  CopyFiles $R0 $0
  ;Start the uninstaller using the option to not copy itself
  ExecWait '$0 _?=$INSTDIR'


  IfErrors no_remove_uninstaller
!macro UninstallExisting exitcode uninstcommand
    ; In most cases the uninstall is successful at this point.
Push `${uninstcommand}`
    ; You may also consider using a registry key to check whether
Call UninstallExisting
    ; the user has chosen to uninstall. If you are using an uninstaller
Pop ${exitcode}
    ; components page, make sure all sections are uninstalled.
!macroend
    goto done
Function UninstallExisting
  no_remove_uninstaller:
Exch $1 ; uninstcommand
    MessageBox MB_ICONEXCLAMATION \
Push $2 ; Uninstaller
    "Unable to remove previous version of ${PROGRAM_NAME}"
Push $3 ; Len
    Abort
StrCpy $3 ""
 
StrCpy $2 $1 1
done:
StrCmp $2 '"' qloop sloop
  ; remove the copied uninstaller
sloop:
  Delete '$0'
StrCpy $2 $1 1 $3
IntOp $3 $3 + 1
StrCmp $2 "" +2
StrCmp $2 ' ' 0 sloop
IntOp $3 $3 - 1
Goto run
qloop:
StrCmp $3 "" 0 +2
StrCpy $1 $1 "" 1 ; Remove initial quote
IntOp $3 $3 + 1
StrCpy $2 $1 1 $3
StrCmp $2 "" +2
StrCmp $2 '"' 0 qloop
run:
StrCpy $2 $1 $3 ; Path to uninstaller
StrCpy $1 161 ; ERROR_BAD_PATHNAME
GetFullPathName $3 "$2\.." ; $InstDir
IfFileExists "$2" 0 +4
ExecWait '"$2" /S _?=$3' $1 ; This assumes the existing uninstaller is a NSIS uninstaller, other uninstallers don't support /S nor _?=
IntCmp $1 0 "" +2 +2 ; Don't delete the installer if it was aborted
Delete "$2" ; Delete the uninstaller
RMDir "$3" ; Try to delete $InstDir
RMDir "$3\.." ; (Optional) Try to delete the parent of $InstDir
Pop $3
Pop $2
Exch $1 ; exitcode
FunctionEnd


Function .onInit
ReadRegStr $0 HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "UninstallString"
${If} $0 != ""
${AndIf} ${Cmd} `MessageBox MB_YESNO|MB_ICONQUESTION "Uninstall previous version?" /SD IDYES IDYES`
!insertmacro UninstallExisting $0 $0
${If} $0 <> 0
MessageBox MB_YESNO|MB_ICONSTOP "Failed to uninstall, continue anyway?" /SD IDYES IDYES +2
Abort
${EndIf}
${EndIf}
FunctionEnd
FunctionEnd
Page Directory
Page InstFiles
Section
SetOutPath $InstDir
File "/oname=$InstDir\App.exe" "${__FILE__}" ; Dummy file
WriteUninstaller "$InstDir\Uninst.exe"
WriteRegStr HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "DisplayName" "NSIS Test"
WriteRegStr HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "UninstallString" '"$InstDir\Uninst.exe"'
WriteRegStr HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "QuietUninstallString" '"$InstDir\Uninst.exe" /S'
SectionEnd
Section Uninstall
Delete "$InstDir\App.exe"
DeleteRegKey HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}"
Delete "$InstDir\Uninst.exe"
RMDir "$InstDir"
SectionEnd
</highlight-nsis>
</highlight-nsis>
[[Category:System Related Functions]]

Latest revision as of 13:45, 3 September 2019

Author: Anders (talk, contrib)


This code can be used to uninstall a existing installation. The previous installation must also be a NSIS based install.

RequestExecutionLevel User
InstallDir "$LocalAppData\Programs\NSISTest"
!define UninstId "NSISTest" ; You might want to use a GUID here
 
!include LogicLib.nsh
 
 
!macro UninstallExisting exitcode uninstcommand
Push `${uninstcommand}`
Call UninstallExisting
Pop ${exitcode}
!macroend
Function UninstallExisting
Exch $1 ; uninstcommand
Push $2 ; Uninstaller
Push $3 ; Len
StrCpy $3 ""
StrCpy $2 $1 1
StrCmp $2 '"' qloop sloop
sloop:
	StrCpy $2 $1 1 $3
	IntOp $3 $3 + 1
	StrCmp $2 "" +2
	StrCmp $2 ' ' 0 sloop
	IntOp $3 $3 - 1
	Goto run
qloop:
	StrCmp $3 "" 0 +2
	StrCpy $1 $1 "" 1 ; Remove initial quote
	IntOp $3 $3 + 1
	StrCpy $2 $1 1 $3
	StrCmp $2 "" +2
	StrCmp $2 '"' 0 qloop
run:
	StrCpy $2 $1 $3 ; Path to uninstaller
	StrCpy $1 161 ; ERROR_BAD_PATHNAME
	GetFullPathName $3 "$2\.." ; $InstDir
	IfFileExists "$2" 0 +4
	ExecWait '"$2" /S _?=$3' $1 ; This assumes the existing uninstaller is a NSIS uninstaller, other uninstallers don't support /S nor _?=
	IntCmp $1 0 "" +2 +2 ; Don't delete the installer if it was aborted
	Delete "$2" ; Delete the uninstaller
	RMDir "$3" ; Try to delete $InstDir
	RMDir "$3\.." ; (Optional) Try to delete the parent of $InstDir
Pop $3
Pop $2
Exch $1 ; exitcode
FunctionEnd
 
 
Function .onInit
ReadRegStr $0 HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "UninstallString"
${If} $0 != ""
${AndIf} ${Cmd} `MessageBox MB_YESNO|MB_ICONQUESTION "Uninstall previous version?" /SD IDYES IDYES`
	!insertmacro UninstallExisting $0 $0
	${If} $0 <> 0
		MessageBox MB_YESNO|MB_ICONSTOP "Failed to uninstall, continue anyway?" /SD IDYES IDYES +2
			Abort
	${EndIf}
${EndIf}
FunctionEnd
 
Page Directory
Page InstFiles
 
Section
SetOutPath $InstDir
File "/oname=$InstDir\App.exe" "${__FILE__}" ; Dummy file
WriteUninstaller "$InstDir\Uninst.exe"
WriteRegStr HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "DisplayName" "NSIS Test"
WriteRegStr HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "UninstallString" '"$InstDir\Uninst.exe"'
WriteRegStr HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "QuietUninstallString" '"$InstDir\Uninst.exe" /S'
SectionEnd
 
Section Uninstall
Delete "$InstDir\App.exe"
DeleteRegKey HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}"
Delete "$InstDir\Uninst.exe"
RMDir "$InstDir"
SectionEnd