2using System.Diagnostics;
4using System.Threading.Tasks;
6using Microsoft.Extensions.Logging;
7using Microsoft.Win32.SafeHandles;
17 public int Id {
get; }
32 return handle.PrivateMemorySize64;
36 logger.LogWarning(ex,
"Failed to get PID {pid}'s memory usage!",
Id);
55 readonly global::System.Diagnostics.Process
handle;
89 global::System.Diagnostics.Process
handle,
90 CancellationTokenSource? readerCts,
95 this.handle =
handle ??
throw new ArgumentNullException(nameof(
handle));
107 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
117 Startup = Task.Factory.StartNew(
122 handle.WaitForInputIdle();
126 logger.LogTrace(ex,
"WaitForInputIdle() failed, this is normal.");
129 CancellationToken.None,
131 TaskScheduler.Current);
133 logger.LogTrace(
"Created process ID: {pid}",
Id);
139 if (Interlocked.Exchange(ref
disposed, 1) != 0)
142 logger.LogTrace(
"Disposing PID {pid}...",
Id);
158 throw new InvalidOperationException(
"Output/Error stream reading was not enabled!");
160 return readTask.WaitAsync(cancellationToken);
169 logger.LogTrace(
"PID {pid} already exited",
Id);
175 logger.LogTrace(
"Terminating PID {pid}...",
Id);
177 if (!
handle.WaitForExit(5000))
178 logger.LogWarning(
"WaitForExit() on PID {pid} timed out!",
Id);
182 logger.LogDebug(e,
"PID {pid} termination exception!",
Id);
190 var targetPriority = higher ? ProcessPriorityClass.AboveNormal : ProcessPriorityClass.BelowNormal;
193 handle.PriorityClass = targetPriority;
194 logger.LogTrace(
"Set PID {pid} to {targetPriority} priority",
Id, targetPriority);
198 logger.LogWarning(ex,
"Unable to set priority for PID {id} to {targetPriority}!",
Id, targetPriority);
209 logger.LogTrace(
"Suspended PID {pid}",
Id);
213 logger.LogError(e,
"Failed to suspend PID {pid}!",
Id);
225 logger.LogTrace(
"Resumed PID {pid}",
Id);
229 logger.LogError(e,
"Failed to resume PID {pid}!",
Id);
239 logger.LogTrace(
"PID {pid} Username: {username}",
Id, result);
244 public ValueTask
CreateDump(
string outputFile,
bool minidump, CancellationToken cancellationToken)
246 ArgumentNullException.ThrowIfNull(outputFile);
249 logger.LogTrace(
"Dumping PID {pid} to {dumpFilePath}...",
Id, outputFile);
265 catch (OperationCanceledException ex)
267 logger.LogTrace(ex,
"Process lifetime task cancelled!");
268 hasExited =
handle.HasExited;
274 var exitCode =
handle.ExitCode;
275 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.
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 o...
void AdjustPriority(bool higher)
Set's the owned global::System.Diagnostics.Process.PriorityClass to a non-normal value.
ValueTask CreateDump(string outputFile, bool minidump, CancellationToken cancellationToken)
Create a dump file of the process.A ValueTask representing the running operation.
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".
long? MemoryUsage
Gets the process' memory usage in bytes.
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, bool minidump, 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 global::System.Diagnostics.Process.
Abstraction over a global::System.Diagnostics.Process.