我正在为部署在Windows Server 2008 R2和Windows Server 2012环境中的客户端重构自定义流程监控应用程序。
监控应用程序需要识别崩溃的,无响应的进程(在任务管理器中标识为“无响应”),强制终止它们并重新启动。受监视的进程可以是基于控制台或基于Win32的应用程序,主要是基于控制台的。
Process.Responding属性在此特定情况下没有用,因为它确定UI是否正在响应(可能使用类似的方法“下面的方法来更新此属性)。
如果导入基于控制台的应用程序不符合以下条件,IsHungAppWindow方法也无用:
如果应用程序没有等待输入,不在启动处理中,并且在5秒的内部超时时间内没有调用PeekMessage,则认为应用程序没有响应。
我使用WMI系统类监视进程时,Win32_Process
WMI类的Status属性是没有用的:
此属性未实现,并且不会为此类的任何实例填充。它始终为NULL。
Win32_Process
WMI类的ExecutionState属性没有用,因为它似乎也没有实现。虽然没有明确说明,但在运行本地测试后,它会重复返回NULL
,而third party则表明这一点。
如何合理地确定流程是否无响应?
答案 0 :(得分:2)
我可以确定的最佳答案和解决方案是监视Windows事件查看器应用程序日志中的Application Error
和Application Hang
事件。
从.NET 3.5开始,实现了一个方便的类,以避免读取和过滤整个事件日志:EventLogWatcher允许观察特定事件。
以下是一个非常基本的示例,使用XPath查询按EventID
,Level
和ApplicationName
进行过滤:
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]
轻松扩展。