@@ -46,11 +46,87 @@ function Write-Warn {
4646 Write-Host $Message
4747}
4848
49+ # Exit code when a Windows native binary cannot load required DLLs (STATUS_DLL_NOT_FOUND).
50+ $script :DllNotFoundExitCode = -1073741515
51+
52+ function Test-IsDllNotFoundExitCode {
53+ param ([int ]$ExitCode )
54+ if ($ExitCode -eq $script :DllNotFoundExitCode ) {
55+ return $true
56+ }
57+ if ($ExitCode -eq 3221225781 ) {
58+ return $true
59+ }
60+ if ($ExitCode -lt 0 ) {
61+ $hex = ' {0:X8}' -f ($ExitCode -band 0xFFFFFFFF )
62+ return $hex -eq ' C0000135'
63+ }
64+ return $false
65+ }
66+
67+ function Get-DllNotFoundInstallMessage {
68+ $arch = if ($env: PROCESSOR_ARCHITECTURE -eq " ARM64" ) { " arm64" } else { " x64" }
69+ $vcUrl = if ($arch -eq " arm64" ) {
70+ " https://aka.ms/vs/17/release/vc_redist.arm64.exe"
71+ } else {
72+ " https://aka.ms/vs/17/release/vc_redist.x64.exe"
73+ }
74+ return @"
75+ vp.exe could not start (exit code 0xC0000135).
76+ This usually means Microsoft Visual C++ 2015-2022 Redistributable ($arch ) is not installed.
77+
78+ Install: $vcUrl
79+ Then re-run: irm https://vite.plus/ps1 | iex
80+ "@
81+ }
82+
83+ # Internal stop signal: halts install without re-printing an error we already wrote.
84+ $script :InstallStopSignal = ' VP_INSTALL_STOP'
85+
86+ function Test-IsInstallStopException {
87+ param (
88+ [System.Management.Automation.ErrorRecord ]$ErrorRecord
89+ )
90+ return $ErrorRecord.Exception.Message -eq $script :InstallStopSignal
91+ }
92+
93+ function Test-ShouldKeepShellOpenAfterFailure {
94+ # Only `irm ... | iex` typed in an already-open interactive shell should keep the
95+ # session alive. CI, script files, and `powershell -Command "..."` must exit non-zero.
96+ if ($env: CI -eq " true" ) {
97+ return $false
98+ }
99+ if ($PSCommandPath ) {
100+ return $false
101+ }
102+ if (-not [Environment ]::UserInteractive) {
103+ return $false
104+ }
105+ try {
106+ $commandLine = (Get-CimInstance Win32_Process - Filter " ProcessId=$PID " ).CommandLine
107+ if ($commandLine -match ' (^|\s)-Command(\s|$)' ) {
108+ return $false
109+ }
110+ } catch {
111+ return $false
112+ }
113+ return $true
114+ }
115+
116+ function Exit-Installer {
117+ param ([int ]$Code = 1 )
118+ $global :LASTEXITCODE = $Code
119+ if (-not (Test-ShouldKeepShellOpenAfterFailure )) {
120+ exit $Code
121+ }
122+ throw $script :InstallStopSignal
123+ }
124+
49125function Write-Error-Exit {
50126 param ([string ]$Message )
51127 Write-Host " error: " - ForegroundColor Red - NoNewline
52128 Write-Host $Message
53- exit 1
129+ Exit-Installer
54130}
55131
56132function Test-ReleaseAgeError {
@@ -114,11 +190,26 @@ function Write-ReleaseAgeOverride {
114190}
115191
116192function Write-InstallFailure {
117- param ([string ]$LogPath )
193+ param (
194+ [string ]$LogPath ,
195+ [int ]$ExitCode = 0
196+ )
197+
198+ if (Test-IsDllNotFoundExitCode $ExitCode ) {
199+ $message = Get-DllNotFoundInstallMessage
200+ if ($env: CI -eq " true" ) {
201+ Write-Host " error: " - ForegroundColor Red - NoNewline
202+ Write-Host $message
203+ Exit-Installer
204+ }
205+ Write-Error - Exit $message
206+ }
207+
118208 if ($env: CI -eq " true" ) {
119209 Write-Host " error: " - ForegroundColor Red - NoNewline
120210 Write-Host " Failed to install dependencies. Log output:"
121211 Get-Content - Path $LogPath | ForEach-Object { Write-Host $_ }
212+ Exit-Installer
122213 } else {
123214 Write-Error - Exit " Failed to install dependencies. See log for details: $LogPath "
124215 }
@@ -157,6 +248,7 @@ function Get-PackageMetadata {
157248 try {
158249 $script :PackageMetadata = Invoke-RestMethod $metadataUrl
159250 } catch {
251+ if (Test-IsInstallStopException $_ ) { throw }
160252 # Try to extract npm error message from response
161253 $errorMsg = $_.ErrorDetails.Message
162254 if ($errorMsg ) {
@@ -166,6 +258,7 @@ function Get-PackageMetadata {
166258 Write-Error - Exit " Failed to fetch version '${versionPath} ': $ ( $errorJson.error ) `n URL: $metadataUrl "
167259 }
168260 } catch {
261+ if (Test-IsInstallStopException $_ ) { throw }
169262 # JSON parsing failed, fall through to generic error
170263 }
171264 }
@@ -179,6 +272,7 @@ function Get-PackageMetadata {
179272 try {
180273 $script :PackageMetadata = $script :PackageMetadata | ConvertFrom-Json
181274 } catch {
275+ if (Test-IsInstallStopException $_ ) { throw }
182276 # Not valid JSON - treat as plain string error
183277 Write-Error - Exit " Failed to fetch version '${versionPath} ': $script :PackageMetadata `n URL: $metadataUrl "
184278 }
@@ -593,16 +687,14 @@ function Main {
593687 $retryExitCode = $LASTEXITCODE
594688 $retryOutput | Out-File $installLog
595689 if ($retryExitCode -ne 0 ) {
596- Write-InstallFailure $installLog
597- exit 1
690+ Write-InstallFailure - LogPath $installLog - ExitCode $retryExitCode
598691 }
599692 } else {
600693 Write-ReleaseAgeFailure $installLog
601- exit 1
694+ Exit-Installer
602695 }
603696 } else {
604- Write-InstallFailure $installLog
605- exit 1
697+ Write-InstallFailure - LogPath $installLog - ExitCode $installExitCode
606698 }
607699 }
608700 } finally {
@@ -749,4 +841,14 @@ exec "`$VP_HOME/current/bin/vp.exe" "`$@"
749841 Write-Host " "
750842}
751843
752- Main
844+ try {
845+ Main
846+ } catch {
847+ if (Test-IsInstallStopException $_ ) {
848+ if (Test-ShouldKeepShellOpenAfterFailure ) {
849+ return
850+ }
851+ exit $global :LASTEXITCODE
852+ }
853+ throw
854+ }
0 commit comments