查找进程是否正在响应而不使用System.Diagnostics.Process.Responding

今天是个好日子。

这个问题是解决问题的另一个问题的一部分,我意识到我认为这是问题,毕竟它不是。 还要感谢我学到了一些东西。

我的应用程序使用IE浏览器进行大量工作,并且IE会不时重定向到一个网站,这些网站有一些不好的Javascript代码,最终导致IE界面被阻塞。 因此,一旦我的应用程序中的所有内容都在相同的Thread上运行,就会阻止我的应用程

为了解决这个问题,在启动时我的应用程序在另一个Thread中运行一个static method ,如果IE正在响应,每15秒进行一次简单的检查,如果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中,他报告没有MainWindowHandle属性的IE进程,而在Windows 7中,当IE没有响应时他也能正确报告。 但在XP中,所有使用MainWindowHandle 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;
}
链接地址: http://www.djcxy.com/p/48271.html

上一篇: Find if process is responding without using System.Diagnostics.Process.Responding

下一篇: IntelliJ flash compiling slow with swc