!include "nsProcess.nsh" !macro customCheckAppRunning ${GetParameters} $R0 ClearErrors ${GetOptions} $R0 "/YCODEWAITPID=" $R1 ${IfNot} ${Errors} ${If} $R1 <= 0 SetErrorLevel 2 Quit ${EndIf} ; Updates wait for this instance only; never kill another installation. ; ?e captures OpenProcess's native error in the same System call. System::Call 'kernel32::OpenProcess(i 0x100000, i 0, i R1) p .R2 ?e' Pop $R3 ${If} $R2 != 0 System::Call 'kernel32::WaitForSingleObject(p R2, i 120000) i .R4' System::Call 'kernel32::CloseHandle(p R2)' ${If} $R4 != 0 SetErrorLevel 2 Quit ${EndIf} ${ElseIf} $R3 != 87 ; ERROR_INVALID_PARAMETER means the watched PID already exited. SetErrorLevel 2 Quit ${EndIf} ; Renderer children can outlive the PID. Check both the normal wait path and ; the ERROR_INVALID_PARAMETER path for this exact installed executable. System::Call 'kernel32::SetEnvironmentVariable(t "YCODE_UPDATE_TARGET_DIR", t "$INSTDIR\${APP_EXECUTABLE_FILENAME}") i .R4' ${If} $R4 == 0 SetErrorLevel 2 Quit ${EndIf} nsExec::ExecToStack `"$PowerShellPath" -NoLogo -NoProfile -NonInteractive -Command "trap { exit 2 }; $$ErrorActionPreference='Stop'; $$target=([IO.Path]::GetFullPath($$env:YCODE_UPDATE_TARGET_DIR)).TrimEnd([char]92); $$deadline=[DateTime]::UtcNow.AddSeconds(5); do { $$all=@(Get-CimInstance Win32_Process | Where-Object { $$_.Name -ieq '${APP_EXECUTABLE_FILENAME}' }); $$found=$$false; foreach ($$process in $$all) { if (-not $$process.ExecutablePath) { $$found=$$true; continue }; if ((([IO.Path]::GetFullPath($$process.ExecutablePath)).TrimEnd([char]92)) -ieq $$target) { $$found=$$true; break } }; if (-not $$found) { exit 0 }; Start-Sleep -Milliseconds 500 } while ([DateTime]::UtcNow -lt $$deadline); exit 1"` Pop $R4 Pop $R5 System::Call 'kernel32::SetEnvironmentVariable(t "YCODE_UPDATE_TARGET_DIR", p 0) i .R5' StrCmp $R4 "0" +3 SetErrorLevel 2 Quit ${Else} ; For manual setup/uninstall, refuse to proceed while YCode is open. !insertmacro nsProcess::FindProcess "${APP_EXECUTABLE_FILENAME}" $R0 ${If} $R0 == 0 MessageBox MB_OK|MB_ICONEXCLAMATION "Please close ${PRODUCT_NAME} before continuing." /SD IDOK SetErrorLevel 2 Quit ${EndIf} ${If} $R0 != 603 SetErrorLevel 2 Quit ${EndIf} ${EndIf} !macroend