Skip to content

Commit 14200b9

Browse files
committed
fix(cli): fix PowerShell install errors on Windows (#1284)
## Summary - Add `Unblock-File` after downloading binaries to strip Zone.Identifier (Mark of the Web), preventing Windows SmartScreen/Defender "Access Denied" errors - Replace `*> $installLog` with captured output + `Out-File` to fix PowerShell 7.6 `StandardOutputEncoding` error - Add PowerShell 7.6 CI test job for regression coverage ## Details Three related issues all stem from Windows security blocking downloaded executables: 1. **#901 — `vp.exe` blocked by Windows Security**: Defender flags the downloaded binary due to MOTW Zone.Identifier ADS. Users had to manually add exclusions. 2. **#1019 — `StandardOutputEncoding` error (PowerShell 7.6)**: The `*>` redirection operator on native commands causes a .NET `InvalidOperationException` when running interactively (real console attached). Also reported "Access Denied" when running `vp.exe`. 3. **#1226 — `Failed to download Node.js runtime: Access is denied. (os error 5)`**: `vp.exe` starts but its file operations (locking, renaming) are restricted by Defender due to MOTW, causing the Node.js runtime download to fail. **Fix**: `Unblock-File` strips the MOTW from all `.exe` files in `$BinDir` immediately after extraction, before `vp.exe install --silent` runs. Closes #901 Closes #1019 Closes #1226
1 parent 35ce525 commit 14200b9

File tree

2 files changed

+88
-2
lines changed

2 files changed

+88
-2
lines changed

.github/workflows/test-standalone-install.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,86 @@ jobs:
474474
vp upgrade --rollback
475475
vp --version
476476
477+
test-install-ps1-v76:
478+
name: Test install.ps1 (Windows x64, PowerShell 7.6)
479+
runs-on: windows-latest
480+
permissions:
481+
contents: read
482+
steps:
483+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
484+
485+
- name: Install PowerShell 7.6
486+
shell: pwsh
487+
run: |
488+
dotnet tool install --global PowerShell --version 7.6.0
489+
$pwsh76 = "$env:USERPROFILE\.dotnet\tools\pwsh.exe"
490+
echo "PWSH76=$pwsh76" >> $env:GITHUB_ENV
491+
$ver = & $pwsh76 -NoProfile -Command '$PSVersionTable.PSVersion.ToString()'
492+
Write-Host "PowerShell version: $ver"
493+
if (-not $ver.StartsWith("7.6")) {
494+
Write-Error "Expected PowerShell 7.6.x but got $ver"
495+
exit 1
496+
}
497+
498+
- name: Run install.ps1 via iex under PowerShell 7.6
499+
shell: pwsh
500+
run: |
501+
& $env:PWSH76 -NoProfile -Command "Get-Content ./packages/cli/install.ps1 -Raw | Invoke-Expression"
502+
503+
- name: Set PATH
504+
shell: bash
505+
run: |
506+
echo "$USERPROFILE\.vite-plus\bin" >> $GITHUB_PATH
507+
508+
- name: Verify installation
509+
shell: pwsh
510+
working-directory: ${{ runner.temp }}
511+
run: |
512+
Write-Host "PATH: $env:Path"
513+
vp --version
514+
vp --help
515+
vp create vite --no-interactive --no-agent -- hello --no-interactive -t vanilla
516+
cd hello
517+
vp run build
518+
vp --version
519+
520+
- name: Verify bin setup
521+
shell: pwsh
522+
run: |
523+
$binPath = "$env:USERPROFILE\.vite-plus\bin"
524+
Get-ChildItem -Force $binPath
525+
if (-not (Test-Path $binPath)) {
526+
Write-Error "Bin directory not found: $binPath"
527+
exit 1
528+
}
529+
530+
$expectedShims = @("node.exe", "npm.exe", "npx.exe")
531+
foreach ($shim in $expectedShims) {
532+
$shimFile = Join-Path $binPath $shim
533+
if (-not (Test-Path $shimFile)) {
534+
Write-Error "Shim not found: $shimFile"
535+
exit 1
536+
}
537+
Write-Host "Found shim: $shimFile"
538+
}
539+
where.exe node
540+
where.exe npm
541+
where.exe npx
542+
where.exe vp
543+
544+
$env:Path = "$env:USERPROFILE\.vite-plus\bin;$env:Path"
545+
vp env doctor
546+
vp env run --node 24 -- node -p "process.versions"
547+
548+
- name: Verify upgrade
549+
shell: pwsh
550+
run: |
551+
vp upgrade --check
552+
vp upgrade 0.1.14-alpha.1
553+
vp --version
554+
vp upgrade --rollback
555+
vp --version
556+
477557
test-install-ps1:
478558
name: Test install.ps1 (Windows x64)
479559
runs-on: windows-latest

packages/cli/install.ps1

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,10 @@ function Main {
350350
}
351351
}
352352

353+
# Remove Zone.Identifier (Mark of the Web) from downloaded binaries so
354+
# Windows SmartScreen / Defender won't block execution.
355+
Get-ChildItem -Path $BinDir -Filter "*.exe" | Unblock-File
356+
353357
# Generate wrapper package.json that declares vite-plus as a dependency.
354358
# pnpm will install vite-plus and all transitive deps via `vp install`.
355359
# The packageManager field pins pnpm to a known-good version.
@@ -376,8 +380,10 @@ function Main {
376380
try {
377381
# Use cmd /c so CI=true is scoped to the child process only,
378382
# avoiding leaking it into the user's shell session.
379-
cmd /c "set CI=true && `"$BinDir\vp.exe`" install --silent" *> $installLog
380-
if ($LASTEXITCODE -ne 0) {
383+
$output = cmd /c "set CI=true && `"$BinDir\vp.exe`" install --silent" 2>&1
384+
$installExitCode = $LASTEXITCODE
385+
$output | Out-File $installLog
386+
if ($installExitCode -ne 0) {
381387
Write-Host "error: Failed to install dependencies. See log for details: $installLog" -ForegroundColor Red
382388
exit 1
383389
}

0 commit comments

Comments
 (0)