Refactor Windows installer update process to improve file handling and cleanup
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

- Updated the `swapUpdateStaging` macro to streamline the update process by swapping the old and new versions of Farm Control more efficiently.
- Introduced a cleanup step to remove leftover `.old` directories from previous updates, enhancing the installer’s reliability.
- Improved logging for better visibility during the update and removal processes, ensuring users are informed of actions taken.
This commit is contained in:
Tom Butcher 2026-08-08 23:16:03 +01:00
parent 29bf25cc20
commit 2216a28ce3

View File

@ -121,103 +121,72 @@ Var FinalInstDir
${EndIf}
!macroend
; Returns 0 in $R9 when $R8 can be renamed (file unlocked / path free).
; _ID must be unique per insert so labels do not collide.
!macro tryRenameProbe _ID
StrCpy $R9 1
${IfNot} ${FileExists} "$R8"
StrCpy $R9 0
Goto try_rename_probe_done_${_ID}
${EndIf}
ClearErrors
Rename "$R8" "$R8.updating"
${If} ${Errors}
Goto try_rename_probe_done_${_ID}
${EndIf}
; Leave the .updating name the whole tree is about to be deleted.
StrCpy $R9 0
try_rename_probe_done_${_ID}:
!macroend
; Wait until the live install directory is released by the quitting app.
!macro waitForInstallDirWritable
!insertmacro progressStatus "Waiting for Farm Control to release install files..."
DetailPrint "Waiting for install directory to become writable..."
StrCpy $R7 0
wait_install_writable:
; Probe the main binaries rename fails while the process still holds them.
StrCpy $R8 "$FinalInstDir\bin\FarmControl.exe"
!insertmacro tryRenameProbe farmcontrol
${If} $R9 != 0
Goto wait_install_writable_retry
${EndIf}
StrCpy $R8 "$FinalInstDir\bin\launcher.exe"
!insertmacro tryRenameProbe launcher
${If} $R9 != 0
Goto wait_install_writable_retry
${EndIf}
; Also probe creating a temp file in the install root.
ClearErrors
FileOpen $R8 "$FinalInstDir\.farmcontrol-write-probe" w
${If} $R8 == ""
Goto wait_install_writable_retry
${EndIf}
FileClose $R8
Delete "$FinalInstDir\.farmcontrol-write-probe"
Goto wait_install_writable_done
wait_install_writable_retry:
IntOp $R7 $R7 + 1
${If} $R7 < 60
Sleep 500
Goto wait_install_writable
${EndIf}
!insertmacro progressFailure "Could not access the previous Farm Control installation."
Abort
wait_install_writable_done:
!macroend
; Swap order: Farm Control -> .old, Farm Control.new -> Farm Control, delete .old.
!macro swapUpdateStaging
!insertmacro progressPhase "Applying update"
!insertmacro progressStatus "Replacing Farm Control with the new version..."
DetailPrint "Replacing Farm Control with staged update..."
; Clear a leftover .old from a previous interrupted update.
${If} ${FileExists} "$FinalInstDir.old"
DetailPrint "Removing leftover Farm Control.old..."
RMDir /r "$FinalInstDir.old"
${EndIf}
${If} ${FileExists} "$FinalInstDir"
!insertmacro waitForInstallDirWritable
!insertmacro progressStatus "Replacing Farm Control with the new version..."
DetailPrint "Replacing Farm Control with staged update..."
!insertmacro progressStatus "Waiting for Farm Control to release install files..."
DetailPrint "Waiting to rename install directory to Farm Control.old..."
StrCpy $R7 0
swap_delete_retry:
RMDir /r "$FinalInstDir"
${If} ${FileExists} "$FinalInstDir"
swap_rename_old_retry:
ClearErrors
Rename "$FinalInstDir" "$FinalInstDir.old"
${If} ${Errors}
IntOp $R7 $R7 + 1
${If} $R7 < 20
${If} $R7 < 60
Sleep 500
Goto swap_delete_retry
Goto swap_rename_old_retry
${EndIf}
!insertmacro progressFailure "Could not remove the previous Farm Control installation."
!insertmacro progressFailure "Could not move the previous Farm Control installation aside."
Abort
${EndIf}
${EndIf}
!insertmacro progressStatus "Activating new Farm Control installation..."
DetailPrint "Activating staged update..."
DetailPrint "Renaming Farm Control.new to Farm Control..."
ClearErrors
Rename "$INSTDIR" "$FinalInstDir"
${If} ${Errors}
; Best-effort rollback so the previous install is usable again.
${If} ${FileExists} "$FinalInstDir.old"
Rename "$FinalInstDir.old" "$FinalInstDir"
${EndIf}
!insertmacro progressFailure "Could not activate the new Farm Control installation."
Abort
${EndIf}
StrCpy $INSTDIR $FinalInstDir
!insertmacro progressLog "installer:STATUS:Update files activated"
${If} ${FileExists} "$FinalInstDir.old"
!insertmacro progressStatus "Removing previous Farm Control installation..."
DetailPrint "Removing Farm Control.old..."
StrCpy $R7 0
swap_delete_old_retry:
RMDir /r "$FinalInstDir.old"
${If} ${FileExists} "$FinalInstDir.old"
IntOp $R7 $R7 + 1
${If} $R7 < 20
Sleep 500
Goto swap_delete_old_retry
${EndIf}
; New version is already active; leftover .old is non-fatal.
DetailPrint "Warning: could not fully remove Farm Control.old"
!insertmacro progressLog "installer:STATUS:Warning: could not fully remove previous installation"
${EndIf}
${EndIf}
!macroend
!macro uninstallPreviousFarmControl