SentinelProcess 1.0.0
There is a newer version of this package available.
See the version list below for details.
See the version list below for details.
dotnet add package SentinelProcess --version 1.0.0
NuGet\Install-Package SentinelProcess -Version 1.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SentinelProcess" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add SentinelProcess --version 1.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: SentinelProcess, 1.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install SentinelProcess as a Cake Addin #addin nuget:?package=SentinelProcess&version=1.0.0 // Install SentinelProcess as a Cake Tool #tool nuget:?package=SentinelProcess&version=1.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
SentinelProcess
SentinelProcess is a robust library for managing and monitoring the lifecycle of .NET processes. It provides parent-child process monitoring, graceful shutdown handling, and platform-optimized process management features.
Key Features
- Process lifecycle management (start, stop, monitoring)
- Automatic termination linked to parent process monitoring
- Platform-optimized process termination handling (Windows/Unix)
- Process output stream capture
- Extensible logging system
- Flexible configuration options
- Asynchronous operation support
Installation
dotnet add package SentinelProcess
Usage
Basic Example
Here's a complete example of a basic parent-child process monitoring scenario.
Parent Process (MainApp)
using SentinelProcess.Builder;
using SentinelProcess.Extensions;
using SentinelProcess.Logging;
// Custom console logger implementation
class ConsoleLogger : ISentinelLogger
{
public void LogDebug(string message) =>
Console.WriteLine($"[DEBUG] {message}");
public void LogError(string message, Exception? exception = null) =>
Console.WriteLine($"[ERROR] {message} {exception?.Message}");
public void LogInformation(string message) =>
Console.WriteLine($"[INFO] {message}");
public void LogWarning(string message) =>
Console.WriteLine($"[WARN] {message}");
}
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine($"MainApp started (PID: {Environment.ProcessId})");
var logger = new ConsoleLogger();
try
{
var sentinel = ProcessSentinelBuilder.Create()
.ConfigureProcess(config =>
{
config.ProcessName = "SubApp";
config.ExecutablePath = "path/to/SubApp.exe";
config.Arguments = "argument1 argument2";
config.RunInBackground = false;
config.MonitorParentProcess = true;
config.ShutdownTimeout = TimeSpan.FromSeconds(5);
config.EnvironmentVariables = new Dictionary<string, string>
{
["CUSTOM_VARIABLE"] = "test_value"
};
config.WorkingDirectory = Path.GetDirectoryName(config.ExecutablePath);
})
.UseLogger(logger)
.Build();
// Register event handlers
sentinel.OutputReceived += (s, e) =>
Console.WriteLine($"SubApp output: {e.Data}");
sentinel.ErrorReceived += (s, e) =>
Console.WriteLine($"SubApp error: {e.Data}");
sentinel.StateChanged += (s, e) =>
Console.WriteLine($"SubApp state changed: {e.PreviousState} -> {e.CurrentState}");
// Start SubApp
await sentinel.StartAsync();
Console.WriteLine("Press any key to stop SubApp...");
Console.ReadKey();
// Gracefully stop SubApp
await sentinel.StopAsync();
await sentinel.DisposeAsync();
}
catch (Exception ex)
{
logger.LogError("Unexpected error occurred", ex);
}
}
}
Child Process (SubApp)
class Program
{
private static readonly CancellationTokenSource _cts = new();
static async Task Main(string[] args)
{
Console.WriteLine($"SubApp started (PID: {Environment.ProcessId})");
Console.WriteLine($"Parent process ID: {Environment.GetEnvironmentVariable("SENTINEL_PARENT_PID")}");
Console.WriteLine($"Custom environment variable: {Environment.GetEnvironmentVariable("CUSTOM_VARIABLE")}");
Console.WriteLine($"Received arguments: {string.Join(", ", args)}");
// Register Ctrl+C handler
Console.CancelKeyPress += (s, e) =>
{
e.Cancel = true;
_cts.Cancel();
};
try
{
while (!_cts.Token.IsCancellationRequested)
{
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Working...");
await Task.Delay(1000, _cts.Token);
}
// Cleanup on normal shutdown
Console.WriteLine("Performing graceful shutdown...");
await Task.Delay(500);
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation cancelled");
}
catch (Exception ex)
{
Console.Error.WriteLine($"Error occurred: {ex.Message}");
Environment.Exit(1);
}
}
}
Advanced Configuration Options
Configuration Details
Option | Description | Default | Usage Example |
---|---|---|---|
ProcessName | Process identifier | - | config.ProcessName = "MyApp" |
ExecutablePath | Executable file path | - | config.ExecutablePath = "path/to/app.exe" |
Arguments | Command line arguments | - | config.Arguments = "--port 8080" |
RunInBackground | Run in background | true | config.RunInBackground = false |
MonitorParentProcess | Enable parent process monitoring | true | config.MonitorParentProcess = true |
ShutdownTimeout | Shutdown wait time | 5 seconds | config.ShutdownTimeout = TimeSpan.FromSeconds(10) |
WorkingDirectory | Working directory | Current directory | config.WorkingDirectory = "path/to/dir" |
EnvironmentVariables | Environment variable settings | Empty dictionary | config.EnvironmentVariables["KEY"] = "value" |
Process States and Events
Process State Definitions
public enum ProcessState
{
NotStarted, // Initial state
Starting, // Starting up
Running, // Running
Stopping, // Shutting down
Stopped, // Normally terminated
Failed // Error occurred
}
Event Handling
The library provides the following events:
OutputReceived
: Standard output received from processErrorReceived
: Error output received from processStateChanged
: Process state changed
// Event handling example
sentinel.OutputReceived += (sender, args) =>
{
Console.WriteLine($"Output: {args.Data}");
Console.WriteLine($"Timestamp: {args.Timestamp}");
};
sentinel.StateChanged += (sender, args) =>
{
Console.WriteLine($"Previous state: {args.PreviousState}");
Console.WriteLine($"Current state: {args.CurrentState}");
Console.WriteLine($"Timestamp: {args.Timestamp}");
};
Logging System
ISentinelLogger Interface
public interface ISentinelLogger
{
void LogInformation(string message);
void LogWarning(string message);
void LogError(string message, Exception? exception = null);
void LogDebug(string message);
}
Custom Logger Implementation Example
class FileLogger : ISentinelLogger
{
private readonly string _logPath;
public FileLogger(string logPath)
{
_logPath = logPath;
}
public void LogInformation(string message) =>
WriteLog("INFO", message);
public void LogWarning(string message) =>
WriteLog("WARN", message);
public void LogError(string message, Exception? exception = null) =>
WriteLog("ERROR", $"{message} {exception?.ToString() ?? ""}");
public void LogDebug(string message) =>
WriteLog("DEBUG", message);
private void WriteLog(string level, string message)
{
var logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [{level}] {message}";
File.AppendAllLines(_logPath, new[] { logMessage });
}
}
Platform-Specific Process Termination
Windows
- Attempts graceful shutdown via
CloseMainWindow()
method - Calls
Kill(true)
if no response after specified timeout
Unix
- Attempts graceful shutdown via SIGTERM signal
- Sends SIGKILL signal if no response after specified timeout
Best Practices and Considerations
Resource Management
- Release resources through
using
statement or explicitDisposeAsync
calls - Set appropriate shutdown timeouts
- Release resources through
Exception Handling
- Handle exceptions that may occur during process start/stop
- Track issues through logging
Environment Variables
SENTINEL_PARENT_PID
: Parent process ID transmission- Utilize custom environment variables
Working Directory
- Recommended to set explicit working directory
- Exercise caution when using relative paths
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.