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;
126 global::System.Diagnostics.Process
handle,
127 CancellationTokenSource? readerCts,
132 this.handle =
handle ??
throw new ArgumentNullException(nameof(
handle));
144 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
156 Startup = Task.Factory.StartNew(
161 handle.WaitForInputIdle();
165 logger.LogTrace(ex,
"WaitForInputIdle() failed, this is normal.");
168 CancellationToken.None,
170 TaskScheduler.Current);
174 logger.LogTrace(
"Created process ID: {pid}",
Id);
180 if (Interlocked.Exchange(ref
disposed, 1) != 0)
183 logger.LogTrace(
"Disposing PID {pid}...",
Id);
199 throw new InvalidOperationException(
"Output/Error stream reading was not enabled!");
201 return readTask.WaitAsync(cancellationToken);
210 logger.LogTrace(
"PID {pid} already exited",
Id);
216 logger.LogTrace(
"Terminating PID {pid}...",
Id);
218 if (!
handle.WaitForExit(5000))
219 logger.LogWarning(
"WaitForExit() on PID {pid} timed out!",
Id);
223 logger.LogDebug(e,
"PID {pid} termination exception!",
Id);
231 var targetPriority = higher ? ProcessPriorityClass.AboveNormal : ProcessPriorityClass.BelowNormal;
234 handle.PriorityClass = targetPriority;
235 logger.LogTrace(
"Set PID {pid} to {targetPriority} priority",
Id, targetPriority);
239 logger.LogWarning(ex,
"Unable to set priority for PID {id} to {targetPriority}!",
Id, targetPriority);
250 logger.LogTrace(
"Suspended PID {pid}",
Id);
254 logger.LogError(e,
"Failed to suspend PID {pid}!",
Id);
266 logger.LogTrace(
"Resumed PID {pid}",
Id);
270 logger.LogError(e,
"Failed to resume PID {pid}!",
Id);
280 logger.LogTrace(
"PID {pid} Username: {username}",
Id, result);
285 public ValueTask
CreateDump(
string outputFile,
bool minidump, CancellationToken cancellationToken)
287 ArgumentNullException.ThrowIfNull(outputFile);
290 logger.LogTrace(
"Dumping PID {pid} to {dumpFilePath}...",
Id, outputFile);
301 var now = DateTimeOffset.UtcNow;
302 var newTime =
handle.TotalProcessorTime;
310 if (timeDelta != TimeSpan.Zero)
315 logger.LogWarning(ex,
"Error measuring processor time delta!");
334 catch (OperationCanceledException ex)
336 logger.LogTrace(ex,
"Process lifetime task cancelled!");
337 hasExited =
handle.HasExited;
343 var exitCode =
handle.ExitCode;
344 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.
readonly object processTimeMeasureLock
lock object for measuring processor time usage.
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.
DateTimeOffset lastProcessorMeasureTime
The last time MeasureProcessorTimeDelta was called.
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.
double MeasureProcessorTimeDelta()
Gets the estimated CPU usage fraction of the process based on the last time this was called....
double lastProcessorUsageEstimation
The last valid return value of MeasureProcessorTimeDelta.
TimeSpan lastProcessorUsageTime
The last value of global::System.Diagnostics.Process.TotalProcessorTime.
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.
int disposed
If the Process was disposed.
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.