在不使用System.Diagnostics.Process.Responding的情况下查找进程是否响应

时间:2010-08-18 15:58:04

标签: c# windows-xp

大家好日子。

这个问题是another one的一部分,它已经解决了,我意识到我认为这毕竟是问题,但事实并非如此。还是要感谢我,我学到了很多东西。

我的应用程序使用IE进行大量工作,IE不时被重定向到一个网站,其中包含一些不良的Javascript代码,最终阻止了IE界面。一旦我的应用程序上的所有内容都运行在同一个Thread上,就会阻止我的应用程序。

为了解决这个问题,在启动时,我的应用程序在另一个static method中运行Thread每隔15秒进行一次简单检查IE是否响应,如果IE没有响应,他关闭其所有进程,释放我的应用程序主Thread上的锁,然后我的应用程序可以恢复其工作。

要查找IE进程是否正在响应,我有一个简单的代码:

bool terminate = false;
foreach (System.Diagnostics.Process exe in System.Diagnostics.Process.GetProcesses())
{
    if (exe.ProcessName.StartsWith("iexplore"))
    {
        if (exe.Responding == false)
        {
            terminate = true;
            break;
        }
    }
}
// Code to close all IE process's...

为了Process.Responding属性查找进程是否响应,并根据MSDN的信息,此属性需要另一个名为MainWindowHandle的属性才能完成检查过程。如果MainWindowHandle不可用Process.Responding,即使进程没有响应,也始终返回true。

由于某些我不知道的原因。在Windows XP中MainWindowHandle不可用,因此Responding不准确。

这就是为什么我需要知道另一种方法来查找特定进程是否在Windows XP中响应。

感谢任何帮助,谢谢。

PS:如果您想在这里冻结IE网站,请访问:http://aboutmycollege.com/

编辑:遵循0xA3建议:

我经历了所有IE进程检查他们是否有MainWindowHandle属性,那些拥有该属性的人我将Responding属性发送给MessageBox,并且当IE在Windows上没有响应时他们正确报告7但不是XP。

我每15秒执行一次这段代码:

        foreach (System.Diagnostics.Process exe in System.Diagnostics.Process.GetProcesses())
        {
            if (exe.ProcessName.StartsWith("iexplore"))
            {
                if (exe.MainWindowHandle == IntPtr.Zero)
                {
                    System.Windows.Forms.MessageBox.Show("Process doesn't have MainWindowHandle");
                }
                else
                {
                    System.Windows.Forms.MessageBox.Show("Process Responding: " + exe.Responding.ToString());
                }
            }
        }

在Windows 7和Xp中,他报告IE的进程没有MainWindowHandle属性,而在Windows 7中,他也会在IE没有响应时正确报告。但是在XP中,MainWindowHandle的所有IE进程总是响应,即使它们不是。

1 个答案:

答案 0 :(得分:3)

IE是特殊的,因为每个选项卡都有自己的进程,还有一个额外的父IE进程。实际上,只有父进程才有效MainWindowHandle

您是否检查过所有这些进程的MainWindowHandle是否为空?如果不是,我认为您的代码也应该在XP上按预期工作。

<强>更新

由于检查所有IE实例没有帮助,我接下来要尝试的是修改Process.Responding使用的超时。该属性在内部调用SendMessageTimeout api函数,然后检查返回值是否发生超时。如果是这样,则假定该过程挂起。超时是5秒的硬编码值。

您可以使用P / Invoke自己调用SendMessageTimeout并更改超时。可能更短的值会在Windows XP上产生更好的结果:

[DllImport("user32.dll", CharSet=CharSet.Auto)]
static extern IntPtr SendMessageTimeout(
    HandleRef hWnd, 
    int msg, 
    IntPtr wParam, 
    IntPtr lParam, 
    int flags, 
    int timeout, 
    out IntPtr pdwResult);

const int SMTO_ABORTIFHUNG = 2;

bool IsResponding(Process process)
{
    HandeRef handleRef = new HandleRef(process, process.MainWindowHandle);

    int timeout = 2000;
    IntPtr lpdwResult;

    IntPtr lResult = SendMessageTimeout(
        handleRef, 
        0, 
        IntPtr.Zero, 
        IntPtr.Zero, 
        SMTO_ABORTIFHUNG, 
        timeout, 
        out lpdwResult);

    return lResult != IntPtr.Zero;
}