153 lines
4.1 KiB
C#
153 lines
4.1 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Threading;
|
|
|
|
namespace MonsterMonitor.Services
|
|
{
|
|
public sealed class ProcessMonitorService : IDisposable
|
|
{
|
|
private readonly LogService _log;
|
|
private readonly object _sync = new object();
|
|
private readonly Timer _watchdogTimer;
|
|
private Process _process;
|
|
private string _path;
|
|
private string _arguments;
|
|
private bool _stopping;
|
|
|
|
public ProcessMonitorService(LogService log)
|
|
{
|
|
_log = log;
|
|
_watchdogTimer = new Timer(WatchdogTick, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
|
|
}
|
|
|
|
public void Start(string path, string arguments)
|
|
{
|
|
lock (_sync)
|
|
{
|
|
_path = path;
|
|
_arguments = arguments ?? string.Empty;
|
|
_stopping = false;
|
|
EnsureStarted();
|
|
_watchdogTimer.Change(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10));
|
|
}
|
|
}
|
|
|
|
private void EnsureStarted()
|
|
{
|
|
if (IsProcessRunning(_process))
|
|
{
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
if (_process != null)
|
|
{
|
|
_process.Exited -= ProcessOnExited;
|
|
_process.Dispose();
|
|
}
|
|
_process = new Process
|
|
{
|
|
StartInfo = new ProcessStartInfo
|
|
{
|
|
FileName = _path,
|
|
Arguments = _arguments,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true
|
|
},
|
|
EnableRaisingEvents = true
|
|
};
|
|
//_process.Exited += ProcessOnExited;
|
|
_process.Start();
|
|
_log.Info("Процесс ss запущен.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_log.Error("Ошибка запуска ss: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
private void ProcessOnExited(object sender, EventArgs e)
|
|
{
|
|
lock (_sync)
|
|
{
|
|
if (_stopping)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_log.Warn("Процесс ss завершился, запускаю заново.");
|
|
EnsureStarted();
|
|
}
|
|
}
|
|
|
|
private void WatchdogTick(object state)
|
|
{
|
|
lock (_sync)
|
|
{
|
|
if (_stopping)
|
|
{
|
|
return;
|
|
}
|
|
|
|
EnsureStarted();
|
|
}
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
lock (_sync)
|
|
{
|
|
_stopping = true;
|
|
_watchdogTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
|
|
|
|
try
|
|
{
|
|
if (IsProcessRunning(_process))
|
|
{
|
|
_process.Kill();
|
|
_process.WaitForExit(5000);
|
|
_log.Info("Процесс ss остановлен.");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_log.Warn("Не удалось корректно завершить ss: " + ex.Message);
|
|
}
|
|
finally
|
|
{
|
|
if (_process != null)
|
|
{
|
|
_process.Exited -= ProcessOnExited;
|
|
_process.Dispose();
|
|
}
|
|
_process = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool IsProcessRunning(Process process)
|
|
{
|
|
if (process == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
return !process.HasExited;
|
|
}
|
|
catch (InvalidOperationException)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Stop();
|
|
_watchdogTimer.Dispose();
|
|
}
|
|
}
|
|
}
|