Skip to content

Instantly share code, notes, and snippets.

@trackd
Created January 28, 2026 20:31
Show Gist options
  • Select an option

  • Save trackd/25a1f74167fe4a4a76f0db04d60d1914 to your computer and use it in GitHub Desktop.

Select an option

Save trackd/25a1f74167fe4a4a76f0db04d60d1914 to your computer and use it in GitHub Desktop.
function Invoke-Process {
<#
.DESCRIPTION
Starts a new process and captures its output, error, and exit code.
redirects output and error streams for capturing.
doesnt require redirecting to files like Start-Process.
caveat is you cannot get a window and redirected output at the same time.
for that you need to use Start-Process
.PARAMETER Process
The name or path of the process to start.
.PARAMETER Arguments
The arguments to pass to the process as strings.
.PARAMETER ScriptBlock
A script block to execute.
.EXAMPLE
Invoke-Process pwsh { $env:WT_SESSION }
Invoke-Process pwsh '[bool]$env:WT_SESSION'
Invoke-Process cmd '/c ping localhost -n 1'
.NOTES
some weird quote handling may be required depending on the process being started.
Invoke-Process cmd '/c echo Hello, World!'
=> Hello, World!" <- with the extra quote at the end.
#>
[cmdletbinding(DefaultParameterSetName = 'ByString')]
param(
[Parameter(Mandatory, Position = 0)]
[string] $Process,
[Parameter(ParameterSetName = 'ByString', Position = 1)]
[string[]] $Arguments,
[Parameter(ParameterSetName = 'ByScriptBlock', Position = 1)]
[Scriptblock] $ScriptBlock,
[Switch] $ShowWindow
)
try {
if ($Process -match 'powershell|pwsh' -or $ScriptBlock) {
$Arguments = @(
'-NoProfile'
'-EncodedCommand'
if ($ScriptBlock) {
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($ScriptBlock.ToString()))
}
else {
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($Arguments))
}
)
}
# wire up process
$psi = [Diagnostics.ProcessStartInfo]::new($Process, $Arguments)
if ($ShowWindow) {
# we cannot redirect output when showing window..
$psi.UseShellExecute = $true
$psi.CreateNoWindow = $false
$psi.RedirectStandardOutput = $false
$psi.RedirectStandardError = $false
$proc = [Diagnostics.Process]::Start($psi)
# $proc.WaitForExit()
return
}
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$psi.StandardErrorEncoding = $psi.StandardOutputEncoding = $OutputEncoding
$proc = [Diagnostics.Process]::Start($psi)
# read output and error
$cmdline = $proc.CommandLine
$RedirectedOutput = $proc.StandardOutput.ReadToEnd()
$RedirectedError = $proc.StandardError.ReadToEnd()
$proc.WaitForExit()
[PSCustomObject]@{
ExitCode = $proc.ExitCode
Output = $RedirectedOutput.Trim()
Errors = $RedirectedError.Trim()
CommandLine = $cmdline
}
}
catch {
Write-Error $_
}
finally {
if ($proc) {
$proc.Dispose()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment