代码之家  ›  专栏  ›  技术社区  ›  Fábio Antunes

查找进程是否响应而不使用system.diagnostics.process.responding

  •  1
  • Fábio Antunes  · 技术社区  · 14 年前

    大家好。

    这个问题是 another one 当它被解决后,我意识到我所认为的问题终究不是,但多亏了这一点,我学到了一些东西。

    我的应用程序在IE上做了大量的工作,并且不时地,IE被重定向到一个有一些糟糕的javascript代码的网站,最终阻塞了IE界面。因此,当应用程序上的所有内容都运行在同一个应用程序上时,也会阻塞我的应用程序 Thread .

    为了解决这个问题,在启动时,我的应用程序运行一个 static method 在另一个 螺纹 每隔15秒简单检查一下IE是否响应,如果IE没有响应,他会关闭所有进程,释放我的应用程序主服务器上的锁。 螺纹 然后我的申请可以继续它的工作。

    为了找出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 以便完成检查过程。如果 主窗口句柄 不可用 过程.响应 即使进程没有响应,也始终返回true。

    出于某种原因,我不知道。在Windows XP中 主窗口句柄 那里没有,所以 Responding 不准确。

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

    感谢您的帮助。

    PS: 如果你正在寻找一个网站来冻结IE: http://aboutmycollege.com/

    编辑:遵循0xA3建议:

    我检查了所有的过程 主窗口句柄 财产,那些拥有财产的人 响应 属性设置为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());
                    }
                }
            }
    

    在Windows7和XP中,他报告的IE进程没有 主窗口句柄 属性,在Windows7中,当IE没有响应时,他也会正确地报告。但在XP中,所有IE进程都与 主窗口句柄 即使他们没有反应,也总是会做出反应。

    1 回复  |  直到 14 年前
        1
  •  3
  •   Dirk Vollmar    14 年前

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

    你检查过没有 主窗口句柄 所有这些进程都为空吗?如果不是这样的话,我认为您的代码在XP上也应该像预期的那样工作。

    更新

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

    你可以打电话 发送消息超时 使用p/invoke并改变超时。在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;
    }