1 using Microsoft.Extensions.Logging;
4 using System.Threading.Tasks;
14 readonly ILogger<ProcessExecutor>
logger;
28 handle.EnableRaisingEvents =
true;
29 var tcs =
new TaskCompletionSource<int>();
30 handle.Exited += (a, b) =>
35 exitCode = handle.ExitCode;
37 catch (InvalidOperationException)
41 tcs.SetResult(exitCode);
51 public ProcessExecutor(ILogger<ProcessExecutor> logger, ILoggerFactory loggerFactory)
53 this.logger = logger ??
throw new ArgumentNullException(nameof(logger));
54 this.loggerFactory = loggerFactory ??
throw new ArgumentNullException(nameof(loggerFactory));
60 logger.LogDebug(
"Attaching to process {0}...",
id);
61 System.Diagnostics.Process handle;
64 handle =
System.Diagnostics.Process.GetProcessById(
id);
68 logger.LogDebug(
"Unable to get process {0}! Exception: {1}",
id, e);
73 return new Process(handle, AttachExitHandler(handle), null, null, null, loggerFactory.CreateLogger<
Process>(),
true);
83 public IProcess LaunchProcess(
string fileName,
string workingDirectory,
string arguments,
bool readOutput,
bool readError,
bool noShellExecute)
85 logger.LogDebug(
"Launching process in {0}: {1} {2}", workingDirectory, fileName, arguments);
86 var handle =
new System.Diagnostics.Process();
89 handle.StartInfo.FileName = fileName;
90 handle.StartInfo.Arguments = arguments;
91 handle.StartInfo.WorkingDirectory = workingDirectory;
93 handle.StartInfo.UseShellExecute = !(noShellExecute || readOutput || readError);
95 StringBuilder outputStringBuilder = null, errorStringBuilder = null, combinedStringBuilder = null;
96 if (readOutput || readError)
98 combinedStringBuilder =
new StringBuilder();
101 outputStringBuilder =
new StringBuilder();
102 handle.StartInfo.RedirectStandardOutput =
true;
103 handle.OutputDataReceived += (sender, e) =>
105 combinedStringBuilder.Append(Environment.NewLine);
106 combinedStringBuilder.Append(e.Data);
107 outputStringBuilder.Append(Environment.NewLine);
108 outputStringBuilder.Append(e.Data);
113 errorStringBuilder =
new StringBuilder();
114 handle.StartInfo.RedirectStandardError =
true;
115 handle.ErrorDataReceived += (sender, e) =>
117 combinedStringBuilder.Append(Environment.NewLine);
118 combinedStringBuilder.Append(e.Data);
119 errorStringBuilder.Append(Environment.NewLine);
120 errorStringBuilder.Append(e.Data);
125 var lifetimeTask = AttachExitHandler(handle);
131 handle.BeginOutputReadLine();
133 catch (InvalidOperationException) { }
137 handle.BeginErrorReadLine();
139 catch (InvalidOperationException) { }
141 return new Process(handle, lifetimeTask, outputStringBuilder, errorStringBuilder, combinedStringBuilder, loggerFactory.CreateLogger<
Process>(),
false);
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the ProcessExecutor
Use server authentication
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments, bool readOutput, bool readError, bool noShellExecute)
Launch a IProcess
For launching IProcess'
IProcess GetProcess(int id)
Get a IProcess by id
static Task< int > AttachExitHandler(System.Diagnostics.Process handle)
Create a Task<TResult> resulting in the exit code of a given handle
Abstraction over a System.Diagnostics.Process
ProcessExecutor(ILogger< ProcessExecutor > logger, ILoggerFactory loggerFactory)
Construct a ProcessExecutor
readonly ILogger< ProcessExecutor > logger
The ILogger for the ProcessExecutor