2using System.Diagnostics;
4using System.Threading.Tasks;
6using Microsoft.Extensions.Logging;
7using Microsoft.Win32.SafeHandles;
17 public int Id {
get; }
38 readonly global::System.Diagnostics.Process
handle;
72 global::System.Diagnostics.Process
handle,
73 CancellationTokenSource? readerCts,
78 this.handle =
handle ??
throw new ArgumentNullException(nameof(
handle));
90 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
100 Startup = Task.Factory.StartNew(
105 handle.WaitForInputIdle();
109 logger.LogTrace(ex,
"WaitForInputIdle() failed, this is normal.");
112 CancellationToken.None,
114 TaskScheduler.Current);
116 logger.LogTrace(
"Created process ID: {pid}",
Id);
122 if (Interlocked.Exchange(ref
disposed, 1) != 0)
125 logger.LogTrace(
"Disposing PID {pid}...",
Id);
141 throw new InvalidOperationException(
"Output/Error stream reading was not enabled!");
143 return readTask.WaitAsync(cancellationToken);
152 logger.LogTrace(
"PID {pid} already exited",
Id);
158 logger.LogTrace(
"Terminating PID {pid}...",
Id);
160 if (!
handle.WaitForExit(5000))
161 logger.LogWarning(
"WaitForExit() on PID {pid} timed out!",
Id);
165 logger.LogDebug(e,
"PID {pid} termination exception!",
Id);
173 var targetPriority = higher ? ProcessPriorityClass.AboveNormal : ProcessPriorityClass.BelowNormal;
176 handle.PriorityClass = targetPriority;
177 logger.LogTrace(
"Set PID {pid} to {targetPriority} priority",
Id, targetPriority);
181 logger.LogWarning(ex,
"Unable to set priority for PID {id} to {targetPriority}!",
Id, targetPriority);
192 logger.LogTrace(
"Suspended PID {pid}",
Id);
196 logger.LogError(e,
"Failed to suspend PID {pid}!",
Id);
208 logger.LogTrace(
"Resumed PID {pid}",
Id);
212 logger.LogError(e,
"Failed to resume PID {pid}!",
Id);
222 logger.LogTrace(
"PID {pid} Username: {username}",
Id, result);
227 public ValueTask
CreateDump(
string outputFile, CancellationToken cancellationToken)
229 ArgumentNullException.ThrowIfNull(outputFile);
232 logger.LogTrace(
"Dumping PID {pid} to {dumpFilePath}...",
Id, outputFile);
248 catch (OperationCanceledException ex)
250 logger.LogTrace(ex,
"Process lifetime task cancelled!");
251 hasExited =
handle.HasExited;
257 var exitCode =
handle.ExitCode;
258 logger.LogTrace(
"PID {pid} exited with code {exitCode}",
Id, exitCode);
IIOManager that resolves paths to Environment.CurrentDirectory.
const TaskCreationOptions BlockingTaskCreationOptions
The TaskCreationOptions used to spawn Tasks for potentially long running, blocking operations.
Process(IProcessFeatures processFeatures, global::System.Diagnostics.Process handle, CancellationTokenSource? readerCts, Task< string?>? readTask, ILogger< Process > logger, bool preExisting)
Initializes a new instance of the Process class.
ValueTask CreateDump(string outputFile, CancellationToken cancellationToken)
Create a dump file of the process. A ValueTask representing the running operation.
void CheckDisposed()
Throws an ObjectDisposedException if a method of the Process was called after DisposeAsync.
async ValueTask DisposeAsync()
readonly global::System.Diagnostics.Process handle
The global::System.Diagnostics.Process object.
Task< int?> Lifetime
The Task<TResult> resulting in the exit code of the process or null if the process was detached.
Task< string?> GetCombinedOutput(CancellationToken cancellationToken)
Get the stderr and stdout output of the IProcess. A Task<TResult> resulting in the stderr and stdout ...
void AdjustPriority(bool higher)
Set's the owned global::System.Diagnostics.Process.PriorityClass to a non-normal value.
volatile int disposed
If the Process was disposed.
void Terminate()
Asycnhronously terminates the process. To ensure the IProcess has ended, use the IProcessBase....
readonly ILogger< Process > logger
The ILogger for the Process.
void SuspendProcess()
Suspends the process.
readonly CancellationTokenSource cancellationTokenSource
The CancellationTokenSource used to shutdown the readTask and Lifetime.
string GetExecutingUsername()
Get the name of the account executing the IProcess. The name of the account executing the IProcess.
void ResumeProcess()
Resumes the process.
readonly SafeProcessHandle safeHandle
The global::System.Diagnostics.Process.SafeHandle.
readonly IProcessFeatures processFeatures
The IProcessFeatures for the Process.
Task Startup
The Task representing the time until the IProcess becomes "idle".
readonly? Task< string?> readTask
The Task<TResult> resulting in the process' standard output/error text.
async Task< int?> WrapLifetimeTask()
Attaches a log message to the process' exit event.
Abstraction for suspending and resuming processes.
string GetExecutingUsername(global::System.Diagnostics.Process process)
Get the name of the user executing a given process .
ValueTask CreateDump(global::System.Diagnostics.Process process, string outputFile, CancellationToken cancellationToken)
Create a dump file for a given process .
void SuspendProcess(global::System.Diagnostics.Process process)
Suspend a given process .
void ResumeProcess(global::System.Diagnostics.Process process)
Resume a given suspended Process.
Abstraction over a global::System.Diagnostics.Process.