Как определить не отвечающий процесс?
Я выполняю рефакторинг приложения мониторинга пользовательских процессов для клиента, который развернут в средах Windows Server 2008 R2 и Windows Server 2012.
Приложение мониторинга должно идентифицировать сбойные, не отвечающие процессы (в диспетчере задач помеченные как "Не отвечает"), принудительно уничтожать их и перезапускать. Контролируемые процессы могут быть приложениями на основе консоли или Win32, преимущественно на основе консоли.
Свойство Process.Responding в данном конкретном случае бесполезно, так как оно определяет, отвечает ли пользовательский интерфейс (возможно, для обновления этого свойства используется метод "под капотом", аналогичный приведенному ниже).
Метод IsHungAppWindow также бесполезен, если он был импортирован, поскольку консольные приложения не удовлетворяют следующим критериям:
Считается, что приложение не отвечает, если оно не ожидает ввода, не находится в процессе запуска и не вызвало PeekMessage в течение внутреннего периода ожидания 5 секунд.
Свойство Status объекта Win32_Process
Класс WMI бесполезен, если я отслеживаю процессы, используя системные классы WMI, поскольку:
Это свойство не реализовано и не заполняется ни для одного экземпляра этого класса. Это всегда NULL.
Свойство ExecutionState объекта Win32_Process
Класс WMI бесполезен, так как он также не реализован. Хотя это не указано явно, после запуска локальных тестов оно многократно возвращает NULL
и третья сторона указывает на это.
Как я могу разумно определить, являются ли процессы безразличными?
1 ответ
Лучший ответ и решение, которое я могу определить, это контролировать Application Error
а также Application Hang
события из журнала приложений Windows Event Viewer.
Начиная с.NET 3.5 был реализован удобный класс, позволяющий избежать чтения и фильтрации всех журналов событий: EventLogWatcher, позволяющий вместо этого отслеживать определенные события.
Вот очень простой пример, фильтрация по EventID
, Level
а также ApplicationName
используя запрос XPath:
using System.Globalization;
using System.Diagnostics.Eventing.Reader;
EventLogQuery filter = new EventLogQuery("Application", PathType.LogName, "Event[System[Level=2 and (EventID = 1000 or EventID = 1002)] and EventData[Data[1] = \"example.exe\"]]")
EventLogWatcher watcher = new EventLogWatcher(filter);
watcher.EventRecordWritten += Watcher_ApplicationError; // Register our handler
watcher.Enabled = true; // Start delivering events to the handler
private void Watcher_ApplicationError(object sender, EventRecordWrittenEventArgs e)
{
String rawId = e.EventRecord.Properties[8].Value.ToString(); // Faulting process id
Int32 id = -1;
if (!Int32.TryParse(rawId, out id)) // If not integer, possibly hexadecimal
{
if (!Int32.TryParse(rawId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out id)
return; // Unable to read the process id successfully
}
Process unresponsive = Process.GetProcessById(id); // Get the unresponsive process
unresponsive.Kill(); // Kill it
}
Это может быть легко расширено для фильтрации по полностью определенному, ошибочному пути выполнения приложения Properties[10]
,