Auto-uninstall old before installing new: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
m (Updated author and download links, and changed format of some pages.)
(Empty string protection)
 
(13 intermediate revisions by 8 users not shown)
Line 1: Line 1:
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.
{{PageAuthor|Anders}}
[[Category:Code Examples]]
[[Category:Functions_%26_Macros]]


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.
This code can be used to uninstall a existing installation. The previous installation must also be a NSIS based install.


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


  ReadRegStr $R0 HKLM \
  "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" \
  "UninstallString"
  StrCmp $R0 "" done


  MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
!macro UninstallExisting exitcode uninstcommand
  "${PROGRAM_NAME} is already installed. $\n$\nClick `OK` to remove the \
Push `${uninstcommand}`
  previous version or `Cancel` to cancel this upgrade." \
Call UninstallExisting
  IDOK uninst
Pop ${exitcode}
  Abort
!macroend
 
Function UninstallExisting
;Run the uninstaller
Exch $1 ; uninstcommand
uninst:
Push $2 ; Uninstaller
  ClearErrors
Push $3 ; Len
  ExecWait '$R0 _?=$INSTDIR' ;Do not copy the uninstaller to a temp file
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


  IfErrors no_remove_uninstaller
    ;You can either use Delete /REBOOTOK in the uninstaller or add some code
    ;here to remove to remove the uninstaller. Use a registry key to check
    ;whether the user has chosen to uninstall. If you are using an uninstaller
    ;components page, make sure all sections are uninstalled.
  no_remove_uninstaller:
 
done:


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>
Page author: [[User:codehistorian|codehistorian]]

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