jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs

154 lines
3.8 KiB
C#
Raw Normal View History

2019-11-01 17:38:54 +00:00
#pragma warning disable CS1591
2019-12-10 23:13:57 +00:00
#pragma warning disable SA1600
2019-11-01 17:38:54 +00:00
using System;
2016-11-01 04:07:12 +00:00
using System.Diagnostics;
using System.IO;
using System.Threading;
2016-11-01 04:07:12 +00:00
using System.Threading.Tasks;
using MediaBrowser.Model.Diagnostics;
namespace Emby.Server.Implementations.Diagnostics
2016-11-01 04:07:12 +00:00
{
public class CommonProcess : IProcess
{
private readonly Process _process;
2019-03-13 21:32:52 +00:00
private bool _disposed = false;
private bool _hasExited;
2016-11-01 04:07:12 +00:00
public CommonProcess(ProcessOptions options)
{
2019-03-13 21:32:52 +00:00
StartInfo = options;
2016-11-01 04:07:12 +00:00
var startInfo = new ProcessStartInfo
{
Arguments = options.Arguments,
FileName = options.FileName,
WorkingDirectory = options.WorkingDirectory,
UseShellExecute = options.UseShellExecute,
CreateNoWindow = options.CreateNoWindow,
RedirectStandardError = options.RedirectStandardError,
RedirectStandardInput = options.RedirectStandardInput,
2019-03-13 21:32:52 +00:00
RedirectStandardOutput = options.RedirectStandardOutput,
ErrorDialog = options.ErrorDialog
2016-11-01 04:07:12 +00:00
};
if (options.IsHidden)
{
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
}
_process = new Process
{
StartInfo = startInfo
};
if (options.EnableRaisingEvents)
{
_process.EnableRaisingEvents = true;
2019-03-13 21:32:52 +00:00
_process.Exited += OnProcessExited;
2016-11-01 04:07:12 +00:00
}
}
2019-03-13 21:32:52 +00:00
public event EventHandler Exited;
public ProcessOptions StartInfo { get; }
public StreamWriter StandardInput => _process.StandardInput;
public StreamReader StandardError => _process.StandardError;
public StreamReader StandardOutput => _process.StandardOutput;
public int ExitCode => _process.ExitCode;
2018-09-12 17:26:21 +00:00
private bool HasExited
{
get
{
if (_hasExited)
{
return true;
}
try
{
_hasExited = _process.HasExited;
}
catch (InvalidOperationException)
{
_hasExited = true;
}
return _hasExited;
}
}
2016-11-01 04:07:12 +00:00
public void Start()
{
_process.Start();
}
public void Kill()
{
_process.Kill();
}
public bool WaitForExit(int timeMs)
{
return _process.WaitForExit(timeMs);
}
2017-05-26 06:48:54 +00:00
public Task<bool> WaitForExitAsync(int timeMs)
{
2019-03-13 21:32:52 +00:00
// Note: For this function to work correctly, the option EnableRisingEvents needs to be set to true.
if (HasExited)
{
return Task.FromResult(true);
}
2018-09-12 17:26:21 +00:00
timeMs = Math.Max(0, timeMs);
var tcs = new TaskCompletionSource<bool>();
var cancellationToken = new CancellationTokenSource(timeMs).Token;
_process.Exited += (sender, args) => tcs.TrySetResult(true);
cancellationToken.Register(() => tcs.TrySetResult(HasExited));
return tcs.Task;
2017-05-26 06:48:54 +00:00
}
2016-11-01 04:07:12 +00:00
public void Dispose()
{
2019-03-13 21:32:52 +00:00
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
_process?.Dispose();
}
_disposed = true;
}
private void OnProcessExited(object sender, EventArgs e)
{
_hasExited = true;
Exited?.Invoke(this, e);
2016-11-01 04:07:12 +00:00
}
}
}