mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-11-10 21:20:56 +08:00
* fix(gui): stop Windows processes before installing updates Keep the NSIS installer in the current user context. Detect the target GUI and service before updating, and elevate a temporary helper only when stopping them requires administrator access. Stop services through SCM and wait for their processes to exit before closing the GUI. Retain the helper until installation completes so it can restore a previously running service without another UAC prompt. Restore the service on cancellation when its executable still exists. Prepare before Tauri launches an old uninstaller, and cover passive, silent, and direct uninstall paths. Add Windows service lifecycle tests with isolated executable fixtures. * fix(windows): report stopped before normal service exit Report SERVICE_STOPPED with no accepted controls before exiting after an explicit stop or successful completion. Reporting Running at exit makes SCM treat a normal stop as a failure and schedule a restart. This fixes the service lifecycle independently of installer changes. * fix(gui): prevent old services restarting during Windows updates Temporarily disable service startup before requesting a stop, then restore the original startup mode when the update finishes or exits. Released services can exit without reporting Stopped, causing SCM to queue a recovery restart even after an explicit stop request. Extend the Windows fixture to reproduce that exit behavior with failure recovery enabled and check that startup settings are restored. Record the minor directory-change and GUI-relaunch limitation from review. * docs(windows): record installer short-path matching limitation Record the 8.3 path alias mismatch found while testing the installer helper without administrator privileges. Document how to run the fixture with a full temporary-directory path and retain the issue as a minor follow-up without expanding the installer implementation.
96 lines
3.2 KiB
NSIS
96 lines
3.2 KiB
NSIS
!define EASYTIER_INSTALLER_SCRIPT "${__FILEDIR__}\installer-processes.ps1"
|
|
|
|
; Tauri uninstalls the old version on its reinstall page, before PREINSTALL.
|
|
; MUI consumes this callback on the first page (Welcome). Opening the installer
|
|
; alone does not stop anything; the user must first leave the welcome page.
|
|
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE EasyTierPrepareInstall
|
|
!define MUI_CUSTOMFUNCTION_GUIINIT EasyTierInstallerGuiInit
|
|
|
|
Var EasyTierHelper
|
|
Var EasyTierInstallerPid
|
|
Var EasyTierDone
|
|
Var EasyTierFailed
|
|
|
|
!macro EasyTierPrepare RESTORE
|
|
${If} $EasyTierHelper != ""
|
|
Return
|
|
${EndIf}
|
|
InitPluginsDir
|
|
File "/oname=$PLUGINSDIR\installer-processes.ps1" "${EASYTIER_INSTALLER_SCRIPT}"
|
|
System::Call 'kernel32::GetCurrentProcessId() i .r0'
|
|
StrCpy $EasyTierInstallerPid $0
|
|
nsExec::ExecToStack '"$SYSDIR\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "$PLUGINSDIR\installer-processes.ps1" -InstallDir "$INSTDIR" -InstallerPid $EasyTierInstallerPid -RestoreService ${RESTORE}'
|
|
Pop $0
|
|
Pop $1
|
|
${If} $0 != 0
|
|
MessageBox MB_OK|MB_ICONSTOP "Could not close EasyTier:$\r$\n$1" /SD IDOK
|
|
Abort
|
|
${EndIf}
|
|
IntOp $1 $1 + 0
|
|
${If} $1 != 0
|
|
System::Call 'kernel32::OpenEventW(i 0x100000, i 0, w "Local\EasyTierInstaller-$EasyTierInstallerPid-done") p .r0'
|
|
StrCpy $EasyTierDone $0
|
|
System::Call 'kernel32::OpenEventW(i 0x100000, i 0, w "Local\EasyTierInstaller-$EasyTierInstallerPid-failed") p .r0'
|
|
StrCpy $EasyTierFailed $0
|
|
${If} $EasyTierDone == 0
|
|
${OrIf} $EasyTierFailed == 0
|
|
MessageBox MB_OK|MB_ICONSTOP "Could not wait for EasyTier to finish updating." /SD IDOK
|
|
Abort
|
|
${EndIf}
|
|
StrCpy $EasyTierHelper 1
|
|
${EndIf}
|
|
!macroend
|
|
|
|
!macro EasyTierFinish
|
|
${If} $EasyTierHelper != ""
|
|
System::Call 'kernel32::OpenEventW(i 2, i 0, w "Local\EasyTierInstaller-$EasyTierInstallerPid-finish") p .r0'
|
|
${If} $0 != 0
|
|
System::Call 'kernel32::SetEvent(p r0)'
|
|
System::Call 'kernel32::CloseHandle(p r0)'
|
|
${EndIf}
|
|
System::Call 'kernel32::WaitForSingleObject(p $EasyTierDone, i 65000) i .r0'
|
|
System::Call 'kernel32::WaitForSingleObject(p $EasyTierFailed, i 0) i .r1'
|
|
System::Call 'kernel32::CloseHandle(p $EasyTierDone)'
|
|
System::Call 'kernel32::CloseHandle(p $EasyTierFailed)'
|
|
StrCpy $EasyTierHelper ""
|
|
${If} $0 != 0
|
|
${OrIf} $1 != 258
|
|
MessageBox MB_OK|MB_ICONSTOP "Could not restore the EasyTier service. Please check its status in Windows Services." /SD IDOK
|
|
Abort
|
|
${EndIf}
|
|
${EndIf}
|
|
!macroend
|
|
|
|
Function EasyTierPrepareInstall
|
|
!insertmacro EasyTierPrepare 1
|
|
FunctionEnd
|
|
|
|
Function EasyTierInstallerGuiInit
|
|
; Passive installs skip Welcome, but still run the old uninstaller page.
|
|
${GetOptions} $CMDLINE "/P" $0
|
|
${IfNot} ${Errors}
|
|
Call EasyTierPrepareInstall
|
|
${EndIf}
|
|
FunctionEnd
|
|
|
|
Function un.EasyTierPrepareUninstall
|
|
!insertmacro EasyTierPrepare 0
|
|
FunctionEnd
|
|
|
|
!macro NSIS_HOOK_PREINSTALL
|
|
; Silent installs skip all pages. Also handle a fresh/custom install path.
|
|
Call EasyTierPrepareInstall
|
|
!macroend
|
|
|
|
!macro NSIS_HOOK_POSTINSTALL
|
|
!insertmacro EasyTierFinish
|
|
!macroend
|
|
|
|
!macro NSIS_HOOK_PREUNINSTALL
|
|
Call un.EasyTierPrepareUninstall
|
|
!macroend
|
|
|
|
!macro NSIS_HOOK_POSTUNINSTALL
|
|
!insertmacro EasyTierFinish
|
|
!macroend
|