Public/Start-ProcessWithOutput.ps1

function Start-ProcessWithOutput {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)][string]$File,
        [Parameter()][string]$Arguments,
        [string]$WorkingDirectory,
        [switch]$NoEcho
    )
    begin {
        If (-Not $WorkingDirectory) {
            $WorkingDirectory = "$((Get-Location).Path)"
        }

        $exitCode = -1
        $builder = New-Object System.Text.StringBuilder
        $psi = New-Object System.Diagnostics.ProcessStartInfo
        $psi.FileName = $File;
        $psi.Arguments = $Arguments;
        $psi.CreateNoWindow = $true;
        $psi.RedirectStandardError = $true;
        $psi.RedirectStandardOutput = $true;
        $psi.RedirectStandardInput = $true;
        $psi.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden;
        $psi.UseShellExecute = $false;
        $psi.WorkingDirectory = $WorkingDirectory;

        $p = New-Object System.Diagnostics.Process
        $p.StartInfo = $psi
        $p.EnableRaisingEvents = $true;
        $md = @{
            Output = $builder;
            Print = (-Not $NoEcho.IsPresent);
        }
        
        $errEvent = Register-ObjectEvent -InputObject $p -MessageData $md -EventName ErrorDataReceived -Action {
            If ($Event.MessageData.Print) {
                Write-Log ($EventArgs.Data) -Level Error
            }
            $Event.MessageData.Output.AppendLine($EventArgs.Data) | Out-Null
        }
        $outEvent = Register-ObjectEvent -InputObject $p -MessageData $md -EventName OutputDataReceived -Action {
            If ($Event.MessageData.Print) {
                Write-Log ($EventArgs.Data)
            }
            $Event.MessageData.Output.AppendLine($EventArgs.Data) | Out-Null
        }
    }

    process {
        Try {
            $p.Start() | Out-Null
            $p.BeginErrorReadLine()
            $p.BeginOutputReadLine()
            $p.WaitForExit()
            $exitCode = $p.ExitCode
        } Finally {
            Unregister-Event -SubscriptionId $($errEvent.Id)
            Unregister-Event -SubscriptionId $($outEvent.Id)
            $p.Dispose()
        }
    }
    end {
        RETURN @{
            ExitCode = $exitCode;
            Output = $builder.ToString().Trim();
        }
    }
}