Skip to content

Commit

Permalink
Fixed workingdirectory not being used + added RunBlockingWithInput
Browse files Browse the repository at this point in the history
  • Loading branch information
lidgren committed Feb 7, 2025
1 parent 33a55ba commit bec27ca
Showing 1 changed file with 84 additions and 3 deletions.
87 changes: 84 additions & 3 deletions src/ProcessUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,26 @@ public enum RunProcessResult
/// <summary>
/// Run shell command; f.ex. for opening html links. Do not block, return immediately
/// </summary>
public static Process RunShell(string command, string arguments)
public static Process RunShell(string command, string arguments, string workingDirectory = null)
{
var process = new Process();
process.StartInfo.Verb = command;
process.StartInfo.Arguments = arguments;
process.StartInfo.UseShellExecute = true;
if (string.IsNullOrWhiteSpace(workingDirectory) == false)
{
process.StartInfo.WorkingDirectory = workingDirectory;
}
process.Start();
return process;
}

/// <summary>
/// Run shell command; f.ex. for opening html links; blocks until complete or timeout and returns error code
/// </summary>
public static RunProcessResult RunShell(string command, string arguments, out int exitCode, TimeSpan timeout)
public static RunProcessResult RunShell(string command, string arguments, out int exitCode, TimeSpan timeout, string workingDirectory = null)
{
var process = RunShell(command, arguments);
var process = RunShell(command, arguments, workingDirectory);
bool exited = process.WaitForExit((int)timeout.TotalMilliseconds);
if (!exited)
{
Expand Down Expand Up @@ -68,6 +72,10 @@ public static RunProcessResult RunBlocking(
process.StartInfo.Arguments = arguments;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
if (string.IsNullOrWhiteSpace(workingDirectory) == false)
{
process.StartInfo.WorkingDirectory = workingDirectory;
}

var stdOutBdr = new StringBuilder();
process.StartInfo.RedirectStandardOutput = true;
Expand Down Expand Up @@ -115,5 +123,78 @@ public static RunProcessResult RunBlocking(
return RunProcessResult.ExitCodeZero;
return RunProcessResult.ExitCodeNonZero;
}

/// <summary>
/// Does not use shell execute and redirect output; blocks until complete or timeout and returns error code
/// </summary>
public static RunProcessResult RunBlockingWithInput(
string executable,
string arguments,
string workingDirectory,
TimeSpan timeout,
string stdIn,
out int exitCode,
out string stdOut,
out string stdErr)
{
stdOut = "";
stdErr = "";
exitCode = -1;

var process = new Process();
process.StartInfo.FileName = executable;
process.StartInfo.Arguments = arguments;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
if (string.IsNullOrWhiteSpace(workingDirectory) == false)
{
process.StartInfo.WorkingDirectory = workingDirectory;
}

var stdOutBdr = new StringBuilder();
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += (sender, data) =>
{
stdOutBdr.AppendLine(data.Data);
};

var stdErrBdr = new StringBuilder();
process.StartInfo.RedirectStandardError = true;
process.ErrorDataReceived += (sender, data) =>
{
stdErrBdr.AppendLine(data.Data);
};

process.StartInfo.RedirectStandardInput = true;
#if NET5_0_OR_GREATER
process.StartInfo.StandardInputEncoding = Encoding.Latin1;
#endif

bool ok = process.Start();
if (!ok)
return RunProcessResult.FailedToStartProcess;

// write input
using (var writer = process.StandardInput)
{
writer.Write(stdIn);
}

// read output
process.BeginOutputReadLine();
process.BeginErrorReadLine();

bool exited = process.WaitForExit((int)timeout.TotalMilliseconds);
if (!exited)
return RunProcessResult.TimedOut;

stdOut = stdOutBdr.ToString();
stdErr = stdErrBdr.ToString();
exitCode = process.ExitCode;

if (exitCode == 0)
return RunProcessResult.ExitCodeZero;
return RunProcessResult.ExitCodeNonZero;
}
}
}

0 comments on commit bec27ca

Please sign in to comment.