internal/functions/Start-MtGProcess.ps1

$startProcessCode = @"
using System;
using System.Diagnostics;
using System.Threading;
using System.Text;
 
namespace MovieToGif.CSharp
{
    public static class ProcessHelper
    {
        public class ProcessResult
        {
            public ProcessResult(int exitCode, string standardOut, string standardError)
            {
                this.ExitCode = exitCode;
                this.StandardOut = standardOut;
                this.StandardError = standardError;
            }
            public int ExitCode {get;set;}
            public string StandardOut {get;set;}
            public string StandardError {get;set;}
        }
 
        public static ProcessResult StartProcess(string filePath, string[] args, int timeoutInMilliseconds)
        {
            string arguments = string.Join(" ",args);
            //Source: https://stackoverflow.com/questions/139593/processstartinfo-hanging-on-waitforexit-why/139604
            using (Process process = new Process())
            {
                process.StartInfo.FileName = filePath;
                process.StartInfo.Arguments = arguments;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                StringBuilder output = new StringBuilder();
                StringBuilder error = new StringBuilder();
                using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
                using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
                {
                    process.OutputDataReceived += (sender, e) => {
                        if (e.Data == null)
                        {
                            outputWaitHandle.Set();
                        }
                        else
                        {
                            System.Console.WriteLine(e.Data);
                            output.AppendLine(e.Data);
                        }
                    };
                    process.ErrorDataReceived += (sender, e) =>
                    {
                        if (e.Data == null)
                        {
                            errorWaitHandle.Set();
                        }
                        else
                        {
                            System.Console.WriteLine(e.Data);
                            error.AppendLine(e.Data);
                        }
                    };
 
                    process.Start();
 
                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();
 
                    if (process.WaitForExit(timeoutInMilliseconds) &&
                        outputWaitHandle.WaitOne(timeoutInMilliseconds) &&
                        errorWaitHandle.WaitOne(timeoutInMilliseconds))
                    {
                        return new ProcessResult(process.ExitCode,output.ToString(),error.ToString());
                    }
                    else
                    {
                        return new ProcessResult(258,output.ToString(),"ERROR: Timedout waiting for process to exit:" + filePath + " " + arguments);
                    }
                }
            }
        }
    }
}
"@


if (-not ([System.Management.Automation.PSTypeName]'MovieToGif.CSharp.ProcessHelper').Type)
{
    Add-Type -TypeDefinition $startProcessCode
}

function Start-MtGProcess {
    <#
        .SYNOPSIS
        Start process
         
        .DESCRIPTION
        Start process with redirected stdout.
 
        .EXAMPLE
        Start-MtGProcess "c:\temp\some.exe" -Arguments @("--help","me")
 
        .NOTES
        Version: 1.0
        Author: github/trondr
        Company: github/trondr
        Repository: https://github.com/trondr/MovieToGif.git
    #>

    
    [CmdletBinding()]
    param (
        [string]
        $FilePath,
        [string[]]
        $Arguments
    )
    
    begin {
        Assert-FileExists -Path $FilePath -Message "Failed to start process '$FilePath' $Arguments."
    }
    
    process {
        [MovieToGif.CSharp.ProcessHelper]::StartProcess($FilePath, $Arguments,-1)
    }
    
    end {
        
    }
}