Bug 396870 - Add file in use uninstall support (also fixes bug 252273). r=sspitzer, a1.9=mconnor

This commit is contained in:
rob_strong@exchangecode.com 2007-09-21 15:09:04 -07:00
parent e37b8fa76a
commit 53ed7a0b76
4 changed files with 218 additions and 43 deletions

View File

@ -52,6 +52,7 @@ CRCCheck on
!system 'echo ; > options.ini'
!system 'echo ; > components.ini'
!system 'echo ; > shortcuts.ini'
!system 'echo ; > summary.ini'
Var TmpVal
Var StartMenuDir
@ -105,6 +106,7 @@ VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
!insertmacro AddHandlerValues
!insertmacro CloseApp
!insertmacro CreateRegKey
!insertmacro ManualCloseAppPrompt
!insertmacro RegCleanMain
!insertmacro RegCleanUninstall
!insertmacro WriteRegStr2
@ -129,6 +131,7 @@ ShowInstDetails nevershow
ReserveFile options.ini
ReserveFile components.ini
ReserveFile shortcuts.ini
ReserveFile summary.ini
################################################################################
# Modern User Interface - MUI
@ -181,8 +184,10 @@ Page custom preShortcuts leaveShortcuts
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuDir
; Custom Summary Page
Page custom preSummary leaveSummary
; Install Files Page
!define MUI_PAGE_CUSTOMFUNCTION_PRE preInstFiles
!insertmacro MUI_PAGE_INSTFILES
; Finish Page
@ -534,7 +539,7 @@ Function CopyFile
${If} ${Errors}
${LogMsg} "** ERROR Creating Directory: $R1$R3\$R7 **"
StrCpy $0 "$R1$R3\$R7"
${WordReplace} "$(^FileError_NoIgnore)" "\r\n" "$\r$\n" "+*" $0
StrCpy $0 "$(ERROR_CREATE_DIRECTORY)"
MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$0" IDRETRY retry
Quit
${Else}
@ -548,7 +553,7 @@ Function CopyFile
${If} ${Errors}
${LogMsg} "** ERROR Creating Directory: $R1$R3 **"
StrCpy $0 "$R1$R3"
${WordReplace} "$(^FileError_NoIgnore)" "\r\n" "$\r$\n" "+*" $0
StrCpy $0 "$(ERROR_CREATE_DIRECTORY)"
MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$0" IDRETRY retry
Quit
${Else}
@ -590,7 +595,7 @@ Function CopyFile
FunctionEnd
Function LaunchApp
${CloseApp} "true" $(WARN_APP_RUNNING_INSTALL)
${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
Exec "$INSTDIR\${FileMainEXE}"
FunctionEnd
@ -677,7 +682,26 @@ Function preStartMenu
${EndIf}
FunctionEnd
Function preInstFiles
Function preSummary
!insertmacro createSummaryINI
!insertmacro MUI_HEADER_TEXT "$(SUMMARY_PAGE_TITLE)" "$(SUMMARY_PAGE_SUBTITLE)"
; The Summary custom page has a textbox that will automatically receive
; focus. This sets the focus to the Install button instead.
!insertmacro MUI_INSTALLOPTIONS_INITDIALOG "summary.ini"
GetDlgItem $0 $HWNDPARENT 1
System::Call "user32::SetFocus(i r0, i 0x0007, i,i)i"
!insertmacro MUI_INSTALLOPTIONS_SHOW
FunctionEnd
Function leaveSummary
; If there is a pending deletion from a previous uninstall don't allow
; installing until after the system has rebooted.
IfFileExists "$INSTDIR\${FileMainEXE}.moz-delete" +1 +4
MessageBox MB_YESNO "$(WARN_RESTART_REQUIRED_UNINSTALL)" IDNO +2
Reboot
Quit
${If} $InstallType != ${INSTALLTYPE_CUSTOM}
; Set DOMi to be installed
SectionSetFlags ${DOMI_IDX} 1
@ -700,6 +724,7 @@ Function .onInit
!insertmacro MUI_INSTALLOPTIONS_EXTRACT "options.ini"
!insertmacro MUI_INSTALLOPTIONS_EXTRACT "components.ini"
!insertmacro MUI_INSTALLOPTIONS_EXTRACT "shortcuts.ini"
!insertmacro MUI_INSTALLOPTIONS_EXTRACT "summary.ini"
!insertmacro createBasicCustomOptionsINI
!insertmacro createComponentsINI
!insertmacro createShortcutsINI

View File

@ -101,9 +101,9 @@ VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
!insertmacro WriteRegStr2
!insertmacro un.CleanVirtualStore
!insertmacro un.CloseApp
!insertmacro un.GetLongPath
!insertmacro un.GetSecondInstallPath
!insertmacro un.ManualCloseAppPrompt
!insertmacro un.ParseUninstallLog
!insertmacro un.RegCleanMain
!insertmacro un.RegCleanUninstall
@ -145,10 +145,10 @@ ShowUnInstDetails nevershow
!insertmacro MUI_UNPAGE_WELCOME
; Uninstall Confirm Page
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.leaveConfirm
!insertmacro MUI_UNPAGE_CONFIRM
; Remove Files Page
!define MUI_PAGE_CUSTOMFUNCTION_PRE un.preInstFiles
!insertmacro MUI_UNPAGE_INSTFILES
; Finish Page
@ -179,6 +179,18 @@ Section "Uninstall"
DetailPrint $(STATUS_UNINSTALL_MAIN)
SetDetailsPrint none
; Delete the app exe to prevent launching the app while we are uninstalling.
ClearErrors
${DeleteFile} "$INSTDIR\${FileMainEXE}"
${If} ${Errors}
; If the user closed the application it can take several seconds for it to
; shut down completely. If the application is being used by another user we
; can still delete the files when the system is restarted.
Sleep 5000
${DeleteFile} "$INSTDIR\${FileMainEXE}"
ClearErrors
${EndIf}
; Remove registry entries for non-existent apps and for apps that point to our
; install location in the Software\Mozilla key and uninstall registry entries
; that point to our install location for both HKCU and HKLM.
@ -237,18 +249,27 @@ Section "Uninstall"
${EndIf}
${EndIf}
; Remove directories and files we always control
RmDir /r "$INSTDIR\updates"
RmDir /r "$INSTDIR\defaults\shortcuts"
RmDir /r "$INSTDIR\distribution"
Delete "$INSTDIR\removed-files"
; Remove directories and files we always control before parsing the uninstall
; log so empty directories can be removed.
${If} ${FileExists} "$INSTDIR\updates"
RmDir /r /REBOOTOK "$INSTDIR\updates"
${EndIf}
${If} ${FileExists} "$INSTDIR\defaults\shortcuts"
RmDir /r /REBOOTOK "$INSTDIR\defaults\shortcuts"
${EndIf}
${If} ${FileExists} "$INSTDIR\distribution"
RmDir /r /REBOOTOK "$INSTDIR\distribution"
${EndIf}
${If} ${FileExists} "$INSTDIR\removed-files"
Delete /REBOOTOK "$INSTDIR\removed-files"
${EndIf}
; Parse the uninstall log to unregister dll's and remove all installed
; files / directories this install is responsible for.
${un.ParseUninstallLog}
; Remove the uninstall directory that we control
RmDir /r "$INSTDIR\uninstall"
RmDir /r /REBOOTOK "$INSTDIR\uninstall"
; Remove the installation directory if it is empty
${RemoveDir} "$INSTDIR"
@ -257,6 +278,19 @@ Section "Uninstall"
; VirtualStore directory.
${un.CleanVirtualStore}
; If firefox.exe was successfully deleted yet we still need to restart to
; remove other files create a dummy firefox.exe.moz-delete to prevent the
; installer from allowing an install without restart when it is required
; to complete an uninstall.
${If} ${RebootFlag}
${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-delete"
FileOpen $0 "$INSTDIR\${FileMainEXE}.moz-delete" w
FileWrite $0 "Will be deleted on restart"
Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete"
FileClose $0
${EndUnless}
${EndIf}
; Refresh desktop icons otherwise the start menu internet item won't be
; removed and other ugly things will happen like recreation of the app's
; clients registry key by the OS under some conditions.
@ -292,38 +326,27 @@ BrandingText " "
# Page pre and leave functions
; Checks if the app being uninstalled is running.
Function un.preInstFiles
; Try to delete the app executable and if we can't delete it try to close the
; app. This allows running an instance that is located in another directory.
Function un.leaveConfirm
; Try to delete the app executable and if we can't delete it try to find the
; app's message window and prompt the user to close the app. This allows
; running an instance that is located in another directory. If for whatever
; reason there is no message window we will just rename the app's files and
; then remove them on restart if they are in use.
StrCpy $TmpVal ""
ClearErrors
${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
${DeleteFile} "$INSTDIR\${FileMainEXE}"
${EndIf}
${DeleteFile} "$INSTDIR\${FileMainEXE}"
${If} ${Errors}
ClearErrors
${un.CloseApp} "true" $(WARN_APP_RUNNING_UNINSTALL)
; Delete the app exe to prevent launching the app while we are uninstalling.
ClearErrors
${DeleteFile} "$INSTDIR\${FileMainEXE}"
${If} ${Errors}
ClearErrors
${un.CloseApp} "true" $(WARN_APP_RUNNING_UNINSTALL)
ClearErrors
${DeleteFile} "$INSTDIR\${FileMainEXE}"
${EndIf}
${un.ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_UNINSTALL)"
${EndIf}
FunctionEnd
; When we add an optional action to the finish page the cancel button is
; enabled. This disables it and leaves the finish button as the only choice.
Function un.preFinish
!insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "cancelenabled" "0"
; Setup the survey controls, functions, etc. except when the application has
; defined NO_UNINSTALL_SURVEY
!ifdef NO_UNINSTALL_SURVEY
; Do not modify the finish page if there is a reboot pending
${Unless} ${RebootFlag}
!ifdef NO_UNINSTALL_SURVEY
!insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "NumFields" "3"
!else
!else
; Setup the survey controls, functions, etc.
StrCpy $TmpVal "SOFTWARE\Microsoft\IE Setup\Setup"
ClearErrors
ReadRegStr $0 HKLM $TmpVal "Path"
@ -339,9 +362,15 @@ Function un.preFinish
GetFullPathName $TmpVal $0
${If} ${Errors}
!insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "NumFields" "3"
${Else}
; When we add an optional action to the finish page the cancel button
; is enabled. This disables it and leaves the finish button as the
; only choice.
!insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "cancelenabled" "0"
${EndIf}
${EndIf}
!endif
!endif
${EndUnless}
FunctionEnd
################################################################################

View File

@ -62,17 +62,24 @@ OPTIONS_PAGE_TITLE=Setup Type
OPTIONS_PAGE_SUBTITLE=Choose setup options
SHORTCUTS_PAGE_TITLE=Set Up Shortcuts
SHORTCUTS_PAGE_SUBTITLE=Create Program Icons
SUMMARY_PAGE_TITLE=Summary
SUMMARY_PAGE_SUBTITLE=Ready to start installing ${BrandShortName}
SUMMARY_INSTALLED_TO=${BrandShortName} will be installed to the following location:
SUMMARY_CLICK=Click Install to continue.
SURVEY_TEXT=&Tell us what you thought of ${BrandShortName}
LAUNCH_TEXT=&Launch ${BrandFullName} now
WARN_APP_RUNNING_INSTALL=${BrandFullName} must be closed to proceed with the installation.\n\nClick "OK" to exit ${BrandFullName} automatically and continue.
WARN_APP_RUNNING_UNINSTALL=${BrandFullName} must be closed to proceed with the uninstall.\n\nClick "OK" to exit ${BrandFullName} automatically and continue.
CREATE_ICONS_DESC=Create icons for ${BrandShortName}:
ICONS_DESKTOP=On my &Desktop
ICONS_STARTMENU=In my &Start Menu Programs folder
ICONS_QUICKLAUNCH=In my &Quick Launch bar
WARN_MANUALLY_CLOSE_APP_UNINSTALL=${BrandFullName} must be closed to proceed with the uninstall.\n\nPlease close ${BrandFullName} to continue.
WARN_MANUALLY_CLOSE_APP_LAUNCH=${BrandFullName} is already running.\n\nPlease close ${BrandFullName} prior to launching the version you have just installed.
WARN_WRITE_ACCESS=You don't have access to write to the installation directory.\n\nClick OK to select a different directory.
WARN_DISK_SPACE=You don't have sufficient disk space to install to this location.\n\nClick OK to select a different location.
WARN_UNSUPPORTED_MSG=Sorry, ${BrandShortName} can't be installed. This version of ${BrandShortName} requires ${MinUnsupportedVer} or newer.
WARN_RESTART_REQUIRED_UNINSTALL=Your computer must be restarted to complete a previous uninstall of ${BrandShortName}. Do you want to reboot now?
ERROR_CREATE_DIRECTORY=Error creating directory:\n\n$0\n\nClick Cancel to stop the installation or\nRetry to try again.
STATUS_INSTALL_APP=Installing ${BrandShortName}...
STATUS_INSTALL_LANG=Installing Language Files (${AB_CD})...

View File

@ -499,6 +499,37 @@
WriteINIStr "$PLUGINSDIR\options.ini" "Field 7" Bottom "117"
!macroend
!macro createSummaryINI
WriteINIStr "$PLUGINSDIR\summary.ini" "Settings" NumFields "3"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Type "label"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Text "$(SUMMARY_INSTALLED_TO)"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Left "0"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Right "-1"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Top "5"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Bottom "15"
; XXXrstrong - a side affect of using a READONLY textbox is if the path is
; longer than the visible area of the textbox it will display the characters
; at the end and the beginning of the path will be hidden. Since the path has
; to be greater than 74 characters in length I'm not going to spend any
; cycles trying to come up with a workaround.
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" Type "text"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" state "$INSTDIR"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" Left "0"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" Right "-1"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" Top "17"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" Bottom "30"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" flags "READONLY"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Type "label"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Text "$(SUMMARY_CLICK)"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Left "0"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Right "-1"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Top "130"
WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Bottom "150"
!macroend
/**
* DEPRECATED - use GetParent instead.
*/
@ -568,7 +599,7 @@
################################################################################
# Macros for creating Install Options ini files
# Macros for handling files in use
/**
* The macros below will automatically prepend un. to the function names when
@ -593,6 +624,80 @@
!verbose pop
!macroend
/**
* Displays a MessageBox and then calls abort to prevent continuing to the
* next page when the specified Window Class is found.
*
* @param _WINDOW_CLASS
* The Window Class to search for with FindWindow.
* @param _MSG
* The message text to display in the message box.
*
* $R7 = return value from FindWindow
* $R8 = _WINDOW_CLASS
* $R9 = _MSG
*/
!macro ManualCloseAppPrompt
!ifndef ${_MOZFUNC_UN}ManualCloseAppPrompt
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!define ${_MOZFUNC_UN}ManualCloseAppPrompt "!insertmacro ${_MOZFUNC_UN}ManualCloseAppPromptCall"
Function ${_MOZFUNC_UN}ManualCloseAppPrompt
Exch $R9
Exch 1
Exch $R8
Push $R7
FindWindow $R7 "$R8"
IntCmp $R7 0 +3 +1 +1
MessageBox MB_OK|MB_ICONQUESTION "$R9"
Abort
Pop $R7
Exch $R8
Exch 1
Exch $R9
FunctionEnd
!verbose pop
!endif
!macroend
!macro ManualCloseAppPromptCall _WINDOW_CLASS _MSG
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Push "${_WINDOW_CLASS}"
Push "${_MSG}"
Call ManualCloseAppPrompt
!verbose pop
!macroend
!macro un.ManualCloseAppPromptCall _WINDOW_CLASS _MSG
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Push "${_WINDOW_CLASS}"
Push "${_MSG}"
Call un.ManualCloseAppPrompt
!verbose pop
!macroend
!macro un.ManualCloseAppPrompt
!ifndef un.ManualCloseAppPrompt
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!undef _MOZFUNC_UN
!define _MOZFUNC_UN "un."
!insertmacro ManualCloseAppPrompt
!undef _MOZFUNC_UN
!define _MOZFUNC_UN
!verbose pop
!endif
!macroend
/**
* Posts WM_QUIT to the application's message window which is found using the
* message window's class. This macro uses the nsProcess plugin available
@ -2770,7 +2875,7 @@
${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.RemoveDirsCallback"
; Delete the temporary uninstall log file
${DeleteFile} "$TmpVal"
Delete /REBOOTOK "$TmpVal"
end:
@ -2798,7 +2903,16 @@
StrCmp "$R0" "\" +2 +1
StrCpy $R1 "$R9"
${DeleteFile} "$R1"
IfFileExists "$R1" +1 end
Delete "$R1"
IfErrors +1 end
ClearErrors
Rename "$R1" "$R1.moz-delete"
IfErrors +1 +3
Delete /REBOOTOK "$R1"
GoTo end
Delete /REBOOTOK "$R1.moz-delete"
end:
ClearErrors