2using System.Diagnostics;
4using System.Threading.Tasks;
6using Microsoft.Extensions.Logging;
7using Microsoft.Win32.SafeHandles;
17 public int Id {
get; }
30 logger.LogWarning(ex,
"Failed to get PID {pid}'s memory usage!",
Id);
49 return handle.PrivateMemorySize64;
53 logger.LogWarning(ex,
"Failed to get PID {pid}'s memory usage!",
Id);
72 readonly global::System.Diagnostics.Process
handle;
106 global::System.Diagnostics.Process
handle,
107 CancellationTokenSource? readerCts,
112 this.handle =
handle ??
throw new ArgumentNullException(nameof(
handle));
124 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
134 Startup = Task.Factory.StartNew(
139 handle.WaitForInputIdle();
143 logger.LogTrace(ex,
"WaitForInputIdle() failed, this is normal.");
146 CancellationToken.None,
148 TaskScheduler.Current);
150 logger.LogTrace(
"Created process ID: {pid}",
Id);
156 if (Interlocked.Exchange(ref
disposed, 1) != 0)
159 logger.LogTrace(
"Disposing PID {pid}...",
Id);
175 throw new InvalidOperationException(
"Output/Error stream reading was not enabled!");
177 return readTask.WaitAsync(cancellationToken);
186 logger.LogTrace(
"PID {pid} already exited",
Id);
192 logger.LogTrace(
"Terminating PID {pid}...",
Id);
194 if (!
handle.WaitForExit(5000))
195 logger.LogWarning(
"WaitForExit() on PID {pid} timed out!",
Id);
199 logger.LogDebug(e,
"PID {pid} termination exception!",
Id);
207 var targetPriority = higher ? ProcessPriorityClass.AboveNormal : ProcessPriorityClass.BelowNormal;
210 handle.PriorityClass = targetPriority;
211 logger.LogTrace(
"Set PID {pid} to {targetPriority} priority",
Id, targetPriority);
215 logger.LogWarning(ex,
"Unable to set priority for PID {id} to {targetPriority}!",
Id, targetPriority);
226 logger.LogTrace(
"Suspended PID {pid}",
Id);
230 logger.LogError(e,
"Failed to suspend PID {pid}!",
Id);
242 logger.LogTrace(
"Resumed PID {pid}",
Id);
246 logger.LogError(e,
"Failed to resume PID {pid}!",
Id);
256 logger.LogTrace(
"PID {pid} Username: {username}",
Id, result);
261 public ValueTask
CreateDump(
string outputFile,
bool minidump, CancellationToken cancellationToken)
263 ArgumentNullException.ThrowIfNull(outputFile);
266 logger.LogTrace(
"Dumping PID {pid} to {dumpFilePath}...",
Id, outputFile);
282 catch (OperationCanceledException ex)
284 logger.LogTrace(ex,
"Process lifetime task cancelled!");
285 hasExited =
handle.HasExited;
291 var exitCode =
handle.ExitCode;
292 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()
DateTimeOffset? LaunchTime
When the process was started.
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.