Skip to content

Commit a327be4

Browse files
authored
Merge branch 'develop' into support-nowindow
2 parents 1ea1d5d + 288aee9 commit a327be4

3 files changed

Lines changed: 47 additions & 18 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
### Features
44

5+
- **core:** Improve argument concatenation in `Invoke-ExternalCommand` ([#5065](https://github.com/ScoopInstaller/Scoop/issues/5065))
56
- **core:** Support `-NoWindow` for `Invoke-ExternalCommand` ([#5066](https://github.com/ScoopInstaller/Scoop/issues/5066))
67

78
### Bug Fixes
89

10+
- **core:** Avoid deadlock in `Invoke-ExternalCommand` ([#5064](https://github.com/ScoopInstaller/Scoop/issues/5064))
911
- **install:** Move from cache when `--no-cache` is specified ([#5039](https://github.com/ScoopInstaller/Scoop/issues/5039))
1012
- **scoop-status:** Correct formatting of `Info` output ([#5047](https://github.com/ScoopInstaller/Scoop/issues/5047))
1113

lib/core.ps1

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -510,12 +510,12 @@ function Invoke-ExternalCommand {
510510
}
511511
$Process = New-Object System.Diagnostics.Process
512512
$Process.StartInfo.FileName = $FilePath
513-
$Process.StartInfo.Arguments = ($ArgumentList | Select-Object -Unique) -join ' '
514513
$Process.StartInfo.UseShellExecute = $false
515514
if ($LogPath) {
516-
if ($FilePath -match '(^|\W)msiexec($|\W)') {
517-
$Process.StartInfo.Arguments += " /lwe `"$LogPath`""
515+
if ($FilePath -match '^msiexec(.exe)?$') {
516+
$ArgumentList += "/lwe `"$LogPath`""
518517
} else {
518+
$redirectToLogFile = $true
519519
$Process.StartInfo.RedirectStandardOutput = $true
520520
$Process.StartInfo.RedirectStandardError = $true
521521
}
@@ -526,20 +526,47 @@ function Invoke-ExternalCommand {
526526
} else {
527527
$Process.StartInfo.CreateNoWindow = $NoWindow
528528
}
529+
if ($FilePath -match '^((cmd|cscript|wscript|msiexec)(\.exe)?|.*\.(bat|cmd|js|vbs|wsf))$') {
530+
$Process.StartInfo.Arguments = $ArgumentList -join ' '
531+
} elseif ($Process.StartInfo.ArgumentList.Add) {
532+
# ArgumentList is supported in PowerShell 6.1 and later (built on .NET Core 2.1+)
533+
# ref-1: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.argumentlist?view=net-6.0
534+
# ref-2: https://docs.microsoft.com/en-us/powershell/scripting/whats-new/differences-from-windows-powershell?view=powershell-7.2#net-framework-vs-net-core
535+
$ArgumentList | ForEach-Object { $Process.StartInfo.ArgumentList.Add($_) }
536+
} else {
537+
# escape arguments manually in lower versions, refer to https://docs.microsoft.com/en-us/previous-versions/17w5ykft(v=vs.85)
538+
$escapedArgs = $ArgumentList | ForEach-Object {
539+
# escape N consecutive backslash(es), which are followed by a double quote, to 2N consecutive ones
540+
$s = $_ -replace '(\\+)"', '$1$1"'
541+
# escape N consecutive backslash(es), which are at the end of the string, to 2N consecutive ones
542+
$s = $s -replace '(\\+)$', '$1$1'
543+
# escape double quotes
544+
$s = $s -replace '"', '\"'
545+
# quote the argument
546+
"`"$s`""
547+
}
548+
$Process.StartInfo.Arguments = $escapedArgs -join ' '
549+
}
529550
try {
530-
$Process.Start() | Out-Null
551+
[void]$Process.Start()
531552
} catch {
532553
if ($Activity) {
533554
Write-Host "error." -ForegroundColor DarkRed
534555
}
535556
error $_.Exception.Message
536557
return $false
537558
}
538-
if ($LogPath -and ($FilePath -notmatch '(^|\W)msiexec($|\W)')) {
539-
Out-UTF8File -FilePath $LogPath -Append -InputObject $Process.StandardOutput.ReadToEnd()
540-
Out-UTF8File -FilePath $LogPath -Append -InputObject $Process.StandardError.ReadToEnd()
559+
if ($redirectToLogFile) {
560+
# we do this to remove a deadlock potential
561+
# ref: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.standardoutput?view=netframework-4.5#remarks
562+
$stdoutTask = $Process.StandardOutput.ReadToEndAsync()
563+
$stderrTask = $Process.StandardError.ReadToEndAsync()
541564
}
542565
$Process.WaitForExit()
566+
if ($redirectToLogFile) {
567+
Out-UTF8File -FilePath $LogPath -Append -InputObject $stdoutTask.Result
568+
Out-UTF8File -FilePath $LogPath -Append -InputObject $stderrTask.Result
569+
}
543570
if ($Process.ExitCode -ne 0) {
544571
if ($ContinueExitCodes -and ($ContinueExitCodes.ContainsKey($Process.ExitCode))) {
545572
if ($Activity) {
@@ -609,12 +636,12 @@ function movedir($from, $to) {
609636
$proc.StartInfo.RedirectStandardError = $true
610637
$proc.StartInfo.UseShellExecute = $false
611638
$proc.StartInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
612-
$proc.Start()
613-
$out = $proc.StandardOutput.ReadToEnd()
639+
[void]$proc.Start()
640+
$stdoutTask = $proc.StandardOutput.ReadToEndAsync()
614641
$proc.WaitForExit()
615642

616643
if($proc.ExitCode -ge 8) {
617-
debug $out
644+
debug $stdoutTask.Result
618645
throw "Could not find '$(fname $from)'! (error $($proc.ExitCode))"
619646
}
620647

lib/decompress.ps1

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ function Expand-7zipArchive {
2828
$7zPath = Get-HelperPath -Helper 7zip
2929
}
3030
$LogPath = "$(Split-Path $Path)\7zip.log"
31-
$ArgList = @('x', "`"$Path`"", "-o`"$DestinationPath`"", '-y')
31+
$ArgList = @('x', $Path, "-o$DestinationPath", '-y')
3232
$IsTar = ((strip_ext $Path) -match '\.tar$') -or ($Path -match '\.t[abgpx]z2?$')
3333
if (!$IsTar -and $ExtractDir) {
34-
$ArgList += "-ir!`"$ExtractDir\*`""
34+
$ArgList += "-ir!$ExtractDir\*"
3535
}
3636
if ($Switches) {
3737
$ArgList += (-split $Switches)
@@ -53,7 +53,7 @@ function Expand-7zipArchive {
5353
}
5454
if ($IsTar) {
5555
# Check for tar
56-
$Status = Invoke-ExternalCommand $7zPath @('l', "`"$Path`"") -LogPath $LogPath
56+
$Status = Invoke-ExternalCommand $7zPath @('l', $Path) -LogPath $LogPath
5757
if ($Status) {
5858
# get inner tar file name
5959
$TarFile = (Select-String -Path $LogPath -Pattern '[^ ]*tar$').Matches.Value
@@ -97,7 +97,7 @@ function Expand-ZstdArchive {
9797
$LogPath = Join-Path (Split-Path $Path) 'zstd.log'
9898
$DestinationPath = $DestinationPath.TrimEnd('\')
9999
ensure $DestinationPath | Out-Null
100-
$ArgList = @('-d', "`"$Path`"", '--output-dir-flat', "`"$DestinationPath`"", '-f', '-v')
100+
$ArgList = @('-d', $Path, '--output-dir-flat', $DestinationPath, '-f', '-v')
101101

102102
if ($Switches) {
103103
$ArgList += (-split $Switches)
@@ -148,10 +148,10 @@ function Expand-MsiArchive {
148148
}
149149
if ((get_config MSIEXTRACT_USE_LESSMSI)) {
150150
$MsiPath = Get-HelperPath -Helper Lessmsi
151-
$ArgList = @('x', "`"$Path`"", "`"$DestinationPath\\`"")
151+
$ArgList = @('x', $Path, "$DestinationPath\")
152152
} else {
153153
$MsiPath = 'msiexec.exe'
154-
$ArgList = @('/a', "`"$Path`"", '/qn', "TARGETDIR=`"$DestinationPath\\SourceDir`"")
154+
$ArgList = @('/a', "`"$Path`"", '/qn', "TARGETDIR=`"$DestinationPath\SourceDir`"")
155155
}
156156
$LogPath = "$(Split-Path $Path)\msi.log"
157157
if ($Switches) {
@@ -200,7 +200,7 @@ function Expand-InnoArchive {
200200
$Removal
201201
)
202202
$LogPath = "$(Split-Path $Path)\innounp.log"
203-
$ArgList = @('-x', "-d`"$DestinationPath`"", "`"$Path`"", '-y')
203+
$ArgList = @('-x', "-d$DestinationPath", $Path, '-y')
204204
switch -Regex ($ExtractDir) {
205205
'^[^{].*' { $ArgList += "-c{app}\$ExtractDir" }
206206
'^{.*' { $ArgList += "-c$ExtractDir" }
@@ -267,7 +267,7 @@ function Expand-DarkArchive {
267267
$Removal
268268
)
269269
$LogPath = "$(Split-Path $Path)\dark.log"
270-
$ArgList = @('-nologo', "-x `"$DestinationPath`"", "`"$Path`"")
270+
$ArgList = @('-nologo', '-x', $DestinationPath, $Path)
271271
if ($Switches) {
272272
$ArgList += (-split $Switches)
273273
}

0 commit comments

Comments
 (0)