Bug 1451366: Part 2 - Wait after launch from installer r=mhowell draft
authorAdam Gashlin <agashlin@mozilla.com>
Mon, 14 May 2018 14:50:05 -0700
changeset 795028 8afe52da4446577912c13d55110dcc06677d2d76
parent 795027 0629872de43ed312283c01d25fca9036233a61da
child 795029 9ad1eb162f17160c3bb2ecd258ee86fb07c6b940
push id109841
push userbmo:agashlin@mozilla.com
push dateMon, 14 May 2018 21:53:27 +0000
reviewersmhowell
bugs1451366
milestone62.0a1
Bug 1451366: Part 2 - Wait after launch from installer r=mhowell MozReview-Commit-ID: 2pydLr2P0Ju
browser/installer/windows/nsis/installer.nsi
browser/installer/windows/nsis/stub.nsi
toolkit/mozapps/installer/windows/nsis/common.nsh
--- a/browser/installer/windows/nsis/installer.nsi
+++ b/browser/installer/windows/nsis/installer.nsi
@@ -888,28 +888,28 @@ Function LaunchApp
 !ifndef DEV_EDITION
   ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
 !endif
 
   ClearErrors
   ${GetParameters} $0
   ${GetOptions} "$0" "/UAC:" $1
   ${If} ${Errors}
-    Exec "$\"$INSTDIR\${FileMainEXE}$\""
+    ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\""
   ${Else}
     GetFunctionAddress $0 LaunchAppFromElevatedProcess
     UAC::ExecCodeSegment $0
   ${EndIf}
 FunctionEnd
 
 Function LaunchAppFromElevatedProcess
   ; Set our current working directory to the application's install directory
   ; otherwise the 7-Zip temp directory will be in use and won't be deleted.
   SetOutPath "$INSTDIR"
-  Exec "$\"$INSTDIR\${FileMainEXE}$\""
+  ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\""
 FunctionEnd
 
 ################################################################################
 # Language
 
 !insertmacro MOZ_MUI_LANGUAGE 'baseLocale'
 !verbose push
 !verbose 3
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -1656,37 +1656,37 @@ Function LaunchApp
 
   ; Set the current working directory to the installation directory
   SetOutPath "$INSTDIR"
   ClearErrors
   ${GetParameters} $0
   ${GetOptions} "$0" "/UAC:" $1
   ${If} ${Errors}
     ${If} $CheckboxCleanupProfile == 1
-      Exec "$\"$INSTDIR\${FileMainEXE}$\" -reset-profile -migration"
+      ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" -reset-profile -migration"
     ${Else}
-      Exec "$\"$INSTDIR\${FileMainEXE}$\""
+      ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\""
     ${EndIf}
   ${Else}
     StrCpy $R1 $CheckboxCleanupProfile
     GetFunctionAddress $0 LaunchAppFromElevatedProcess
     UAC::ExecCodeSegment $0
   ${EndIf}
 
   StrCpy $AppLaunchWaitTickCount 0
   ${NSD_CreateTimer} WaitForAppLaunch ${AppLaunchWaitIntervalMS}
 FunctionEnd
 
 Function LaunchAppFromElevatedProcess
   ; Set the current working directory to the installation directory
   SetOutPath "$INSTDIR"
   ${If} $R1 == 1
-    Exec "$\"$INSTDIR\${FileMainEXE}$\" -reset-profile -migration"
+    ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" -reset-profile -migration"
   ${Else}
-    Exec "$\"$INSTDIR\${FileMainEXE}$\""
+    ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\""
   ${EndIf}
 FunctionEnd
 
 Function WaitForAppLaunch
   FindWindow $0 "${MainWindowClass}"
   FindWindow $1 "${DialogWindowClass}"
   ${If} $0 <> 0
   ${OrIf} $1 <> 0
--- a/toolkit/mozapps/installer/windows/nsis/common.nsh
+++ b/toolkit/mozapps/installer/windows/nsis/common.nsh
@@ -8109,8 +8109,54 @@
 
   ; Convert from milliseconds to seconds
   System::Int64Op $0 / 1000
   Pop $0
 
   Pop $1
   Exch $0 ; return elapsed seconds
 !macroend
+
+/**
+ * Create a process to execute a command line. If it is successfully created,
+ * wait on it with WaitForInputIdle, to avoid exiting the current process too
+ * early (exiting early can cause the created process's windows to be opened in
+ * the background).
+ *
+ * CMDLINE Is the command line to execute, like the argument to Exec
+ */
+!define ExecAndWaitForInputIdle "!insertmacro ExecAndWaitForInputIdle_"
+!define CREATE_DEFAULT_ERROR_MODE 0x04000000
+!macro ExecAndWaitForInputIdle_ CMDLINE
+  ; derived from https://stackoverflow.com/a/13960786/3444805 by Anders Kjersem
+  Push $0
+  Push $1
+  Push $2
+
+  ; Command line
+  StrCpy $0 ${CMDLINE}
+
+  ; STARTUPINFO
+  System::Alloc 68
+  Pop $1
+  ; fill in STARTUPINFO.cb (first field) with sizeof(STARTUPINFO)
+  System::Call "*$1(i 68)"
+
+  ; PROCESS_INFORMATION
+  System::Call "*(i, i, i, i) i . r2"
+
+  ; CREATE_DEFAULT_ERROR_MODE follows NSIS myCreateProcess used in Exec
+  System::Call "kernel32::CreateProcessW(i 0, t r0, i 0, i 0, i 0, i ${CREATE_DEFAULT_ERROR_MODE}, i 0, i 0, i r1, i r2) i . r0"
+
+  System::Free $1
+  ${If} $0 <> 0
+    System::Call "*$2(i . r0, i . r1)"
+    ; $0: hProcess, $1: hThread
+    System::Call "user32::WaitForInputIdle(i $0, i 10000)"
+    System::Call "kernel32::CloseHandle(i $0)"
+    System::Call "kernel32::CloseHandle(i $1)"
+  ${EndIf}
+  System::Free $2
+
+  Pop $2
+  Pop $1
+  Pop $0
+!macroend