diff --git a/CHANGELOG.md b/CHANGELOG.md index a654e281..b4c75260 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - **scoop-update:** Add support for parallel syncing buckets in PowerShell 7 and improve output ([#5122](https://github.com/ScoopInstaller/Scoop/issues/5122)) - **config:** Support portable config file ([#5369](https://github.com/ScoopInstaller/Scoop/issues/5369)) - **bucket:** Make official buckets higher priority ([#5398](https://github.com/ScoopInstaller/Scoop/issues/5398)) +- **core:** Add `-Quiet` switch for `Invoke-ExternalCommand` ([#5346](https://github.com/ScoopInstaller/Scoop/issues/5346)) ### Bug Fixes diff --git a/lib/core.ps1 b/lib/core.ps1 index 68ad7a3e..7b1cbf0e 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -568,6 +568,9 @@ function Invoke-ExternalCommand { [Parameter(ParameterSetName = "UseShellExecute")] [Switch] $RunAs, + [Parameter(ParameterSetName = "UseShellExecute")] + [Switch] + $Quiet, [Alias("Msg")] [String] $Activity, @@ -597,29 +600,33 @@ function Invoke-ExternalCommand { if ($RunAs) { $Process.StartInfo.UseShellExecute = $true $Process.StartInfo.Verb = 'RunAs' - } else { - $Process.StartInfo.CreateNoWindow = $true } - if ($FilePath -match '^((cmd|cscript|wscript|msiexec)(\.exe)?|.*\.(bat|cmd|js|vbs|wsf))$') { - $Process.StartInfo.Arguments = $ArgumentList -join ' ' - } elseif ($Process.StartInfo.ArgumentList.Add) { - # ArgumentList is supported in PowerShell 6.1 and later (built on .NET Core 2.1+) - # ref-1: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.argumentlist?view=net-6.0 - # 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 - $ArgumentList | ForEach-Object { $Process.StartInfo.ArgumentList.Add($_) } - } else { - # escape arguments manually in lower versions, refer to https://docs.microsoft.com/en-us/previous-versions/17w5ykft(v=vs.85) - $escapedArgs = $ArgumentList | ForEach-Object { - # escape N consecutive backslash(es), which are followed by a double quote, to 2N consecutive ones - $s = $_ -replace '(\\+)"', '$1$1"' - # escape N consecutive backslash(es), which are at the end of the string, to 2N consecutive ones - $s = $s -replace '(\\+)$', '$1$1' - # escape double quotes - $s = $s -replace '"', '\"' - # quote the argument - "`"$s`"" + if ($Quiet) { + $Process.StartInfo.UseShellExecute = $true + $Process.StartInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden + } + if ($ArgumentList.Length -gt 0) { + if ($FilePath -match '^((cmd|cscript|wscript|msiexec)(\.exe)?|.*\.(bat|cmd|js|vbs|wsf))$') { + $Process.StartInfo.Arguments = $ArgumentList -join ' ' + } elseif ($Process.StartInfo.ArgumentList.Add) { + # ArgumentList is supported in PowerShell 6.1 and later (built on .NET Core 2.1+) + # ref-1: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.argumentlist?view=net-6.0 + # 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 + $ArgumentList | ForEach-Object { $Process.StartInfo.ArgumentList.Add($_) } + } else { + # escape arguments manually in lower versions, refer to https://docs.microsoft.com/en-us/previous-versions/17w5ykft(v=vs.85) + $escapedArgs = $ArgumentList | ForEach-Object { + # escape N consecutive backslash(es), which are followed by a double quote, to 2N consecutive ones + $s = $_ -replace '(\\+)"', '$1$1"' + # escape N consecutive backslash(es), which are at the end of the string, to 2N consecutive ones + $s = $s -replace '(\\+)$', '$1$1' + # escape double quotes + $s = $s -replace '"', '\"' + # quote the argument + "`"$s`"" + } + $Process.StartInfo.Arguments = $escapedArgs -join ' ' } - $Process.StartInfo.Arguments = $escapedArgs -join ' ' } try { [void]$Process.Start()