Skip to content

Commit

Permalink
refactor(iec): Rename to 'Start-ExternalProcess'
Browse files Browse the repository at this point in the history
- refactor(iec): Rename some parameters
- feat(iec): Support EnvVars in 'Invoke-ExternalCommand()'
- fix(iec): Redirect output when 'CreateNoWindow'
- fix(iec): Allow empty 'ArgumentList'
- feat(iec): Support 'WorkingDirectory'
  • Loading branch information
niheaven committed Nov 7, 2023
1 parent fb31696 commit ea37a9e
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 66 deletions.
128 changes: 92 additions & 36 deletions lib/core.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -592,65 +592,116 @@ function is_local($path) {
# operations

function run($exe, $arg, $msg, $continue_exit_codes) {
Show-DeprecatedWarning $MyInvocation 'Invoke-ExternalCommand'
Invoke-ExternalCommand -FilePath $exe -ArgumentList $arg -Activity $msg -ContinueExitCodes $continue_exit_codes
Show-DeprecatedWarning $MyInvocation 'Start-ExternalProcess'
Start-ExternalProcess -FilePath $exe -ArgumentList $arg -Prompt $msg -ContinueExitCodes $continue_exit_codes
}

function Invoke-ExternalCommand {
[CmdletBinding(DefaultParameterSetName = "Default")]
[CmdletBinding(DefaultParameterSetName = 'Default')]
[OutputType([Boolean])]
param (
[Parameter(Mandatory = $true,
Position = 0)]
[Alias("Path")]
[Parameter(Mandatory = $true, Position = 0)]
[Alias('Path')]
[ValidateNotNullOrEmpty()]
[String]
$FilePath,
[Parameter(Position = 1)]
[Alias("Args")]
[Alias('Args')]
[String[]]
$ArgumentList,
[Parameter(ParameterSetName = "UseShellExecute")]
[Parameter(ParameterSetName = 'UseShellExecute')]
[Switch]
$RunAs,
[Parameter(ParameterSetName = "UseShellExecute")]
[Parameter(ParameterSetName = 'UseShellExecute')]
[Switch]
$Quiet,
[Alias("Msg")]
[Alias('Msg')]
[String]
$Activity,
[Alias("cec")]
[Alias('cec')]
[Hashtable]
$ContinueExitCodes,
[Parameter(ParameterSetName = "Default")]
[Alias("Log")]
[Parameter(ParameterSetName = 'Default')]
[Alias('Log')]
[String]
$LogPath
)
if ($Activity) {
Write-Host "$Activity " -NoNewline
Show-DeprecatedWarning $MyInvocation 'Start-ExternalProcess'
if ($RunAs) {
Start-ExternalProcess -FilePath $FilePath -ArgumentList $ArgumentList -Prompt $Activity -ContinueExitCodes $ContinueExitCodes -RunAs -Quiet:$Quiet
} else {
Start-ExternalProcess -FilePath $FilePath -ArgumentList $ArgumentList -Prompt $Activity -ContinueExitCodes $ContinueExitCodes -LogName $LogPath
}
}

function Start-ExternalProcess {
[CmdletBinding(DefaultParameterSetName = 'Default')]
[OutputType([Boolean])]
param (
[Parameter(Mandatory = $true, Position = 0)]
[Alias('PSPath', 'Path')]
[ValidateNotNullOrEmpty()]
[String]
$FilePath,
[Parameter(Position = 1)]
[Alias('Args')]
[String[]]
$ArgumentList,
[Parameter(ParameterSetName = 'Default')]
[String]
$WorkingDirectory,
[Parameter(ParameterSetName = 'UseShellExecute')]
[Switch]
$RunAs,
[Parameter(ParameterSetName = 'UseShellExecute')]
[Switch]
$Quiet,
[Alias('Msg')]
[String]
$Prompt,
[Alias('cec')]
[Hashtable]
$ContinueExitCodes,
[Parameter(ParameterSetName = 'Default')]
[Alias('EnvVar')]
[Hashtable]
$EnvironmentVariables,
[Parameter(ParameterSetName = 'Default')]
[Alias('LogPath')]
[String]
$LogName
)
if ($Prompt) {
Write-Host "$Prompt " -NoNewline
}
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo.FileName = $FilePath
$Process.StartInfo.UseShellExecute = $false
if ($LogPath) {
if ($LogName) {
if ($FilePath -match '^msiexec(.exe)?$') {
$ArgumentList += "/lwe `"$LogPath`""
$ArgumentList += "/lwe `"$LogName`""
} else {
$redirectToLogFile = $true
$Process.StartInfo.RedirectStandardOutput = $true
$Process.StartInfo.RedirectStandardError = $true
}
}
if ($RunAs) {
$Process.StartInfo.UseShellExecute = $true
$Process.StartInfo.Verb = 'RunAs'
} else {
$Process.StartInfo.RedirectStandardOutput = $true
$Process.StartInfo.RedirectStandardError = $true
if ($WorkingDirectory) {
$Process.StartInfo.WorkingDirectory = ensure $WorkingDirectory
}
}
if ($Quiet) {
$Process.StartInfo.UseShellExecute = $true
$Process.StartInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
}
if ($ArgumentList.Length -gt 0) {
if ($EnvironmentVariables) {
$EnvironmentVariables.GetEnumerator() | ForEach-Object { $Process.StartInfo.EnvironmentVariables.Add($_.Key, $_.Value) }
}
if ($ArgumentList) {
if ($FilePath -match '^((cmd|cscript|wscript|msiexec)(\.exe)?|.*\.(bat|cmd|js|vbs|wsf))$') {
$Process.StartInfo.Arguments = $ArgumentList -join ' '
} elseif ($Process.StartInfo.ArgumentList.Add) {
Expand All @@ -676,40 +727,45 @@ function Invoke-ExternalCommand {
try {
[void]$Process.Start()
} catch {
if ($Activity) {
Write-Host "error." -ForegroundColor DarkRed
if ($Prompt) {
Write-Host 'error.' -ForegroundColor DarkRed
}
error $_.Exception.Message
return $false
}
if ($redirectToLogFile) {
# we do this to remove a deadlock potential
# ref: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.standardoutput?view=netframework-4.5#remarks
$stdoutTask = $Process.StandardOutput.ReadToEndAsync()
$stderrTask = $Process.StandardError.ReadToEndAsync()
}
# we do this to remove a deadlock potential
# ref: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.standardoutput?view=netframework-4.5#remarks
$stdoutTask = $Process.StandardOutput.ReadToEndAsync()
$stderrTask = $Process.StandardError.ReadToEndAsync()
$Process.WaitForExit()
if ($redirectToLogFile) {
Out-UTF8File -FilePath $LogPath -Append -InputObject $stdoutTask.Result
Out-UTF8File -FilePath $LogPath -Append -InputObject $stderrTask.Result
Out-UTF8File -FilePath $LogName -Append -InputObject $stdoutTask.Result.Trim()
Out-UTF8File -FilePath $LogName -Append -InputObject $stderrTask.Result.Trim()
} else {
if ($stdoutTask.Result) {
$stdoutTask.Result.Trim() | Out-Default
}
if ($stderrTask.Result) {
$stderrTask.Result.Trim() | Out-Default
}
}
if ($Process.ExitCode -ne 0) {
if ($ContinueExitCodes -and ($ContinueExitCodes.ContainsKey($Process.ExitCode))) {
if ($Activity) {
Write-Host "done." -ForegroundColor DarkYellow
if ($Prompt) {
Write-Host 'done.' -ForegroundColor DarkYellow
}
warn $ContinueExitCodes[$Process.ExitCode]
return $true
} else {
if ($Activity) {
Write-Host "error." -ForegroundColor DarkRed
if ($Prompt) {
Write-Host 'error.' -ForegroundColor DarkRed
}
error "Exit code was $($Process.ExitCode)!"
return $false
}
}
if ($Activity) {
Write-Host "done." -ForegroundColor Green
if ($Prompt) {
Write-Host 'done.' -ForegroundColor Green
}
return $true
}
Expand Down
54 changes: 27 additions & 27 deletions lib/decompress.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function Expand-7zipArchive {
} else {
$7zPath = Get-HelperPath -Helper 7zip
}
$LogPath = "$(Split-Path $Path)\7zip.log"
$LogName = "$(Split-Path $Path)\7zip.log"
$DestinationPath = $DestinationPath.TrimEnd('\')
$ArgList = @('x', $Path, "-o$DestinationPath", '-xr!*.nsis', '-y')
$IsTar = ((strip_ext $Path) -match '\.tar$') -or ($Path -match '\.t[abgpx]z2?$')
Expand All @@ -42,22 +42,22 @@ function Expand-7zipArchive {
'Skip' { $ArgList += '-aos' }
'Rename' { $ArgList += '-aou' }
}
$Status = Invoke-ExternalCommand $7zPath $ArgList -LogPath $LogPath
$Status = Start-ExternalProcess $7zPath $ArgList -LogName $LogName
if (!$Status) {
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')"
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogName)`n$(new_issue_msg $app $bucket 'decompress error')"
}
if (!$IsTar -and $ExtractDir) {
movedir "$DestinationPath\$ExtractDir" $DestinationPath | Out-Null
}
if (Test-Path $LogPath) {
Remove-Item $LogPath -Force
if (Test-Path $LogName) {
Remove-Item $LogName -Force
}
if ($IsTar) {
# Check for tar
$Status = Invoke-ExternalCommand $7zPath @('l', $Path) -LogPath $LogPath
$Status = Start-ExternalProcess $7zPath @('l', $Path) -LogName $LogName
if ($Status) {
# get inner tar file name
$TarFile = (Select-String -Path $LogPath -Pattern '[^ ]*tar$').Matches.Value
$TarFile = (Select-String -Path $LogName -Pattern '[^ ]*tar$').Matches.Value
Expand-7zipArchive -Path "$DestinationPath\$TarFile" -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Removal
} else {
abort "Failed to list files in $Path.`nNot a 7-Zip supported archive file."
Expand Down Expand Up @@ -95,7 +95,7 @@ function Expand-ZstdArchive {
$Removal
)
$ZstdPath = Get-HelperPath -Helper Zstd
$LogPath = Join-Path (Split-Path $Path) 'zstd.log'
$LogName = Join-Path (Split-Path $Path) 'zstd.log'
$DestinationPath = $DestinationPath.TrimEnd('\')
ensure $DestinationPath | Out-Null
$ArgList = @('-d', $Path, '--output-dir-flat', $DestinationPath, '-f', '-v')
Expand All @@ -107,16 +107,16 @@ function Expand-ZstdArchive {
# Remove original archive file
$ArgList += '--rm'
}
$Status = Invoke-ExternalCommand $ZstdPath $ArgList -LogPath $LogPath
$Status = Start-ExternalProcess $ZstdPath $ArgList -LogName $LogName
if (!$Status) {
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')"
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogName)`n$(new_issue_msg $app $bucket 'decompress error')"
}
$IsTar = (strip_ext $Path) -match '\.tar$'
if (!$IsTar -and $ExtractDir) {
movedir (Join-Path $DestinationPath $ExtractDir) $DestinationPath | Out-Null
}
if (Test-Path $LogPath) {
Remove-Item $LogPath -Force
if (Test-Path $LogName) {
Remove-Item $LogName -Force
}
if ($IsTar) {
# Check for tar
Expand Down Expand Up @@ -154,13 +154,13 @@ function Expand-MsiArchive {
$MsiPath = 'msiexec.exe'
$ArgList = @('/a', "`"$Path`"", '/qn', "TARGETDIR=`"$DestinationPath\SourceDir`"")
}
$LogPath = "$(Split-Path $Path)\msi.log"
$LogName = "$(Split-Path $Path)\msi.log"
if ($Switches) {
$ArgList += (-split $Switches)
}
$Status = Invoke-ExternalCommand $MsiPath $ArgList -LogPath $LogPath
$Status = Start-ExternalProcess $MsiPath $ArgList -LogName $LogName
if (!$Status) {
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')"
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogName)`n$(new_issue_msg $app $bucket 'decompress error')"
}
if ($ExtractDir -and (Test-Path "$DestinationPath\SourceDir")) {
movedir "$DestinationPath\SourceDir\$ExtractDir" $OriDestinationPath | Out-Null
Expand All @@ -174,8 +174,8 @@ function Expand-MsiArchive {
if (($DestinationPath -ne (Split-Path $Path)) -and (Test-Path "$DestinationPath\$(fname $Path)")) {
Remove-Item "$DestinationPath\$(fname $Path)" -Force
}
if (Test-Path $LogPath) {
Remove-Item $LogPath -Force
if (Test-Path $LogName) {
Remove-Item $LogName -Force
}
if ($Removal) {
# Remove original archive file
Expand All @@ -200,7 +200,7 @@ function Expand-InnoArchive {
[Switch]
$Removal
)
$LogPath = "$(Split-Path $Path)\innounp.log"
$LogName = "$(Split-Path $Path)\innounp.log"
$ArgList = @('-x', "-d$DestinationPath", $Path, '-y')
switch -Regex ($ExtractDir) {
'^[^{].*' { $ArgList += "-c{app}\$ExtractDir" }
Expand All @@ -210,12 +210,12 @@ function Expand-InnoArchive {
if ($Switches) {
$ArgList += (-split $Switches)
}
$Status = Invoke-ExternalCommand (Get-HelperPath -Helper Innounp) $ArgList -LogPath $LogPath
$Status = Start-ExternalProcess (Get-HelperPath -Helper Innounp) $ArgList -LogName $LogName
if (!$Status) {
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')"
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogName)`n$(new_issue_msg $app $bucket 'decompress error')"
}
if (Test-Path $LogPath) {
Remove-Item $LogPath -Force
if (Test-Path $LogName) {
Remove-Item $LogName -Force
}
if ($Removal) {
# Remove original archive file
Expand Down Expand Up @@ -274,17 +274,17 @@ function Expand-DarkArchive {
[Switch]
$Removal
)
$LogPath = "$(Split-Path $Path)\dark.log"
$LogName = "$(Split-Path $Path)\dark.log"
$ArgList = @('-nologo', '-x', $DestinationPath, $Path)
if ($Switches) {
$ArgList += (-split $Switches)
}
$Status = Invoke-ExternalCommand (Get-HelperPath -Helper Dark) $ArgList -LogPath $LogPath
$Status = Start-ExternalProcess (Get-HelperPath -Helper Dark) $ArgList -LogName $LogName
if (!$Status) {
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')"
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogName)`n$(new_issue_msg $app $bucket 'decompress error')"
}
if (Test-Path $LogPath) {
Remove-Item $LogPath -Force
if (Test-Path $LogName) {
Remove-Item $LogName -Force
}
if ($Removal) {
# Remove original archive file
Expand Down
6 changes: 3 additions & 3 deletions lib/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ function install_msi($fname, $dir, $msi) {

$continue_exit_codes = @{ 3010 = "a restart is required to complete installation" }

$installed = Invoke-ExternalCommand 'msiexec' $arg -Activity "Running installer..." -ContinueExitCodes $continue_exit_codes
$installed = Start-ExternalProcess 'msiexec' $arg -Prompt 'Running installer...' -ContinueExitCodes $continue_exit_codes
if(!$installed) {
abort "Installation aborted. You might need to run 'scoop uninstall $app' before trying again."
}
Expand Down Expand Up @@ -766,7 +766,7 @@ function install_prog($fname, $dir, $installer, $global) {
if($prog.endswith('.ps1')) {
& $prog @arg
} else {
$installed = Invoke-ExternalCommand $prog $arg -Activity "Running installer..."
$installed = Start-ExternalProcess $prog $arg -Prompt 'Running installer...'
if(!$installed) {
abort "Installation aborted. You might need to run 'scoop uninstall $app' before trying again."
}
Expand Down Expand Up @@ -819,7 +819,7 @@ function run_uninstaller($manifest, $architecture, $dir) {
if($exe.endswith('.ps1')) {
& $exe @arg
} else {
$uninstalled = Invoke-ExternalCommand $exe $arg -Activity "Running uninstaller..." -ContinueExitCodes $continue_exit_codes
$uninstalled = Start-ExternalProcess $exe $arg -Prompt 'Running uninstaller...' -ContinueExitCodes $continue_exit_codes
if(!$uninstalled) { abort "Uninstallation aborted." }
}
}
Expand Down

0 comments on commit ea37a9e

Please sign in to comment.