










@@ -623,6 +623,53 @@ function Get-PnpmCommandPath {
623623return (Resolve-CommandPath -Candidates @("pnpm.cmd", "pnpm.exe", "pnpm"))
624624}
625625626+function Get-WindowsCommandSafeDirectory {
627+$userHome = [Environment]::GetFolderPath("UserProfile")
628+if (-not [string]::IsNullOrWhiteSpace($userHome) -and (Test-Path $userHome)) {
629+return $userHome
630+ }
631+if (-not [string]::IsNullOrWhiteSpace($env:TEMP) -and (Test-Path $env:TEMP)) {
632+return $env:TEMP
633+ }
634+return $null
635+}
636+637+function Invoke-CommandFromWindowsSafeDirectory {
638+param(
639+ [Parameter(Mandatory = $true)]
640+ [string]$CommandPath,
641+ [string[]]$Arguments = @()
642+ )
643+644+$safeDir = Get-WindowsCommandSafeDirectory
645+$pushedLocation = $false
646+try {
647+if (-not [string]::IsNullOrWhiteSpace($safeDir)) {
648+Push-Location -LiteralPath $safeDir
649+$pushedLocation = $true
650+ }
651+& $CommandPath @Arguments
652+ } finally {
653+if ($pushedLocation) {
654+Pop-Location
655+ }
656+ }
657+}
658+659+function Invoke-NpmCommand {
660+param([string[]]$Arguments = @())
661+Invoke-CommandFromWindowsSafeDirectory -CommandPath (Get-NpmCommandPath) -Arguments $Arguments
662+}
663+664+function Invoke-CorepackCommand {
665+param([string[]]$Arguments = @())
666+$corepackCommand = Get-CorepackCommandPath
667+if (-not $corepackCommand) {
668+throw "corepack not found on PATH."
669+ }
670+Invoke-CommandFromWindowsSafeDirectory -CommandPath $corepackCommand -Arguments $Arguments
671+}
672+626673function Get-NpmGlobalBinCandidates {
627674param(
628675 [string]$NpmPrefix
@@ -647,7 +694,7 @@ function Ensure-OpenClawOnPath {
647694648695$npmPrefix = $null
649696try {
650-$npmPrefix = (& (Get-NpmCommandPath) config get prefix 2>$null).Trim()
697+$npmPrefix = (Invoke-NpmCommand -Arguments @("config", "get", "prefix") 2>$null).Trim()
651698 } catch {
652699$npmPrefix = $null
653700 }
@@ -751,8 +798,8 @@ function Ensure-Pnpm {
751798$corepackCommand = Get-CorepackCommandPath
752799if ($corepackCommand) {
753800try {
754-& $corepackCommand enable | Out-Null
755-& $corepackCommand prepare $pnpmSpec --activate | Out-Null
801+Invoke-CorepackCommand -Arguments @("enable") | Out-Null
802+Invoke-CorepackCommand -Arguments @("prepare", $pnpmSpec, "--activate") | Out-Null
756803if (Test-PnpmCommandMatchesVersion -PnpmVersion $pnpmVersion -RepoDir $RepoDir) {
757804Write-Host "[OK] pnpm installed via corepack ($pnpmSpec)" -ForegroundColor Green
758805return
@@ -765,7 +812,7 @@ function Ensure-Pnpm {
765812$prevScriptShell = $env:NPM_CONFIG_SCRIPT_SHELL
766813$env:NPM_CONFIG_SCRIPT_SHELL = "cmd.exe"
767814try {
768-& (Get-NpmCommandPath) install -g $pnpmSpec
815+Invoke-NpmCommand -Arguments @("install", "-g", $pnpmSpec)
769816 } finally {
770817$env:NPM_CONFIG_SCRIPT_SHELL = $prevScriptShell
771818 }
@@ -776,6 +823,52 @@ function Ensure-Pnpm {
776823}
777824778825# Install OpenClaw
826+function Resolve-LocalNpmPackagePath {
827+param([string]$PackagePath)
828+829+try {
830+return (Resolve-Path -LiteralPath $PackagePath -ErrorAction Stop).ProviderPath
831+ } catch {
832+return [System.IO.Path]::GetFullPath($PackagePath)
833+ }
834+}
835+836+function Resolve-LocalNpmPackageInstallSpec {
837+param([string]$InstallSpec)
838+839+if ([string]::IsNullOrWhiteSpace($InstallSpec)) {
840+return $InstallSpec
841+ }
842+if ($InstallSpec -match '^file:(?<path>.+)$') {
843+$filePath = $Matches["path"]
844+if (
845+$filePath -match '^/' -or
846+$filePath -match '^\\\\' -or
847+$filePath -match '^[A-Za-z]:[\\/]'
848+ ) {
849+return $InstallSpec
850+ }
851+return ([System.Uri](Resolve-LocalNpmPackagePath -PackagePath $filePath)).AbsoluteUri
852+ }
853+if (
854+$InstallSpec -match '^https?:' -or
855+$InstallSpec -match '^(git\+|github:)' -or
856+$InstallSpec -match '^[A-Za-z]:[\\/]' -or
857+$InstallSpec -match '^\\\\'
858+ ) {
859+return $InstallSpec
860+ }
861+if ($InstallSpec -notmatch '^\.\.?[\\/]' -and $InstallSpec -notmatch '\.tgz$') {
862+return $InstallSpec
863+ }
864+865+try {
866+return (Resolve-LocalNpmPackagePath -PackagePath $InstallSpec)
867+ } catch {
868+return $InstallSpec
869+ }
870+}
871+779872function Resolve-NpmOpenClawInstallSpec {
780873param(
781874 [string]$PackageName,
@@ -795,7 +888,7 @@ function Resolve-NpmOpenClawInstallSpec {
795888$trimmedTag -match '^\.\.?[\\/]' -or
796889$trimmedTag -match '\.tgz($|[?#])'
797890 ) {
798-return $trimmedTag
891+return (Resolve-LocalNpmPackageInstallSpec -InstallSpec $trimmedTag)
799892 }
800893801894return "$PackageName@$trimmedTag"
@@ -852,9 +945,9 @@ function Install-OpenClaw {
852945$installSpec = Resolve-NpmOpenClawInstallSpec -PackageName $packageName -RequestedTag $Tag
853946Write-Host "[*] Installing OpenClaw ($installSpec)..." -ForegroundColor Yellow
854947$freshnessArgs = @("--min-release-age=0")
855-$minReleaseAge = (& (Get-NpmCommandPath) config get min-release-age 2>$null)
948+$minReleaseAge = (Invoke-NpmCommand -Arguments @("config", "get", "min-release-age") 2>$null)
856949if ($LASTEXITCODE -ne 0 -or -not $minReleaseAge -or $minReleaseAge.Trim() -eq "null" -or $minReleaseAge.Trim() -eq "undefined") {
857-$beforeValue = (& (Get-NpmCommandPath) config get before 2>$null)
950+$beforeValue = (Invoke-NpmCommand -Arguments @("config", "get", "before") 2>$null)
858951if ($LASTEXITCODE -eq 0 -and $beforeValue -and $beforeValue.Trim() -ne "null" -and $beforeValue.Trim() -ne "undefined") {
859952$freshnessArgs = @("--before=$((Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"))")
860953 }
@@ -876,7 +969,7 @@ function Install-OpenClaw {
876969Remove-Item Env:NPM_CONFIG_BEFORE -ErrorAction SilentlyContinue
877970Remove-Item Env:NPM_CONFIG_MIN_RELEASE_AGE -ErrorAction SilentlyContinue
878971try {
879-$npmOutput = & (Get-NpmCommandPath) install -g @freshnessArgs "$installSpec" 2>&1
972+$npmOutput = Invoke-NpmCommand -Arguments (@("install", "-g") + $freshnessArgs + @("$installSpec")) 2>&1
880973if ($LASTEXITCODE -ne 0) {
881974Write-Host "[!] npm install failed" -ForegroundColor Red
882975if ($npmOutput -match "spawn git" -or $npmOutput -match "ENOENT.*git") {
@@ -1104,7 +1197,7 @@ function Main {
11041197try {
11051198$npmCommand = Get-NpmCommandPath
11061199if ($npmCommand) {
1107-& $npmCommand uninstall -g openclaw 2>$null | Out-Null
1200+Invoke-NpmCommand -Arguments @("uninstall", "-g", "openclaw") 2>$null | Out-Null
11081201Write-Host "[OK] Removed npm global install if present" -ForegroundColor Green
11091202 }
11101203 } catch { }
@@ -1144,7 +1237,7 @@ function Main {
11441237 }
11451238if (-not $installedVersion) {
11461239try {
1147-$npmList = & (Get-NpmCommandPath) list -g --depth 0 --json 2>$null | ConvertFrom-Json
1240+$npmList = Invoke-NpmCommand -Arguments @("list", "-g", "--depth", "0", "--json") 2>$null | ConvertFrom-Json
11481241if ($npmList -and $npmList.dependencies -and $npmList.dependencies.openclaw -and $npmList.dependencies.openclaw.version) {
11491242$installedVersion = $npmList.dependencies.openclaw.version
11501243 }
このコンテンツは慣性聚合(RSSリーダー)によって自動集約されています。参考としてご覧ください。 原文出典 — 著作権は原著者に帰属します。