tags:

views:

92

answers:

1

Good day everyone.

This problem was part of another one which it as been solved, i realized that what i thought it was the problem after all, it wasn't. Still thanks to that I've learned a couple things.

My application does loads of work with IE and from time to time, IE is redirected to a website with some bad Javascript code that ends up blocking IE interface. And consequently blocking my application too once everything on my application is running on the same Thread.

To counteract that problem, at startup my application runs a static method in another Thread that every 15 seconds does a simple check if IE is responding or not, and if IE isn't responding, he closes all its process's, liberating the lock on my application main Thread and then my application can resume its work.

To find if IE process's are responding i had a simple code like this:

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...

In order to the Process.Responding property finds if the process is responding, and according to information on MSDN, this property needs another property named MainWindowHandle to be available in order to complete the process of checking. And if MainWindowHandle isn't available Process.Responding always returns true even if the process isn't responding.

And for some reason which i don't know. In Windows XP MainWindowHandle isn't available there so Responding isn't accurate.

Thats why i need to know another way to find if a specific process is responding or not in Windows XP.

Any help is appreciated, thanks.

PS: If your looking for a website to freeze IE here goes: http://aboutmycollege.com/

EDIT: Following 0xA3 suggestion:

I went through all IE process's checking if they had the MainWindowHandle property, those who had that property i send they Responding property to a MessageBox and they report correctly when IE isn't responding on Windows 7 but not on XP.

I executed this code every 15 seconds:

        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());
                }
            }
        }

In Windows 7 and Xp he reports the Process's of IE that don't have the MainWindowHandle property, and in Windows 7 he also reports correctly when IE isn't responding. But in XP all IE process's with MainWindowHandle are always responding even when they aren't.

+1  A: 

IE is special because each tab has its own process plus there is an additional parent IE process. In fact, only the parent process will have a valid MainWindowHandle.

Did you check whether MainWindowHandle is null for all these processes? If it isn't I think your code should work as expected on XP as well.

Update

Since checking all IE instances didn't help, the next thing I would try is to modify the timeout that is used by Process.Responding. The property internally calls the SendMessageTimeout api function and then checks the return value whether a timeout occurred. If so, the process is assumed to be hanging. The timeout is a hard-coded value of 5 seconds.

You can call SendMessageTimeout yourself using P/Invoke and vary the timeout. Possibly a shorter value would give better results on 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;
}
0xA3
@0xA3: I didn't thought of that, my code only checks the first IE process and then reports back. Just a sec i will check them all.
Fábio Antunes
Your sample code checks all instances though...
0xA3
@0xA3: My code stops checking if a Process.Responding reports false. Notice the break statement.
Fábio Antunes
@Fábio Antunes: If `MainWindowHandle` isn't available `Process.Responding` always returns `true`, so the break statement would not be reached then.
0xA3
@0xA3: Yes exactly. But in the other hand those process's that have `MainWindowHandle` `Process.Responding` is able to return a accurate value if they are responding or not, which it works well on Windows 7, but on Windows XP all process's that have `MainWindowHandle` `Process.Responding` always returns True even if the process isn't responding. Thats the problem.
Fábio Antunes
@0xA3: My friend. THANKS. Worked pretty well, takes a few seconds longer in XP to recognize that IE as stopped responding but finally it did recognized. I used the code you provided and implemented in my Process handler class, and it works like a clock. I would love if you could explain to me what exactly you did.
Fábio Antunes