Jump to content

Ghost Class Window


Recommended Posts

I'm running a script that opens a program with title 'Abc' and does stuff, waits for it to do stuff, and then closes and repeats. Every once in a while the program will freeze with no visible or differentiating text, and my built in time-out mechanism doesn't work (for some reason). I noticed that when the program freezes the Window Info tool shows that the title remains the same, and that the Class changes to 'Ghost'. Which seems reasonable.

So I write a helper script that will kill the program by use of command shell, on the condition:

WinExists("[CLASS:Ghost]")

This behaves like I expect it to, when the Abc window turns into a 'Ghost' window, my helper script kills it. Now when I change that condition to the following:

WinExists("[TITLE:Abc; CLASS:Ghost]")

it behaves strangely. The script calls a command shell to kill the program when it first starts up, way before it sees the frozen ghost class. If you're asking why I'm even adding that extra TITLE constraint when the previous thing works fine, its simply because I need the extra constraint as I'm going to be making more complicated variants and I'd like to make sure the helper script is killing the correct program.

So, why is the extra constraint actually making the condition easier to be met? I thought that the WinExist advanced options are supposed to be an AND condition, meaning the TITLE has to match AND the CLASS has to match.

Thanks.

Link to comment
Share on other sites

It is associated with a process, the code you just gave is pretty much what I'm currently doing. What I need to know now is how to get WinExists() to wait until the window I'm specifying actually exists (both title and class). I have a feeling that WinExists("[TITLE:Abc;... is TRUE when it just sees a title of 'Abc'. I need it to wait until both the title is 'Abc' and the class is 'Ghost'.

Link to comment
Share on other sites

From: The Old New Thing, Friday, January 23, 2004 12:39 PM by Ian Hanschen

This feature is called window ghosting. Basically what happens is if the window manager decides the window is hung, it will capture the contents of it's client area, and create a window on the screen with the class 'ghost', with the contents it was able to capture, and the window styles of the original window(in most cases, iirc). So the window you see on screen when the app is not responding is not actually the app's window, just a replacement that will hang around until the thread responsible for that window starts responding again. The menubar is gone because the fake window does not have a menu, just extra space for it which is painted white. A disabled menubar would probably cause support problems.

This functionality can be disabled using the call DisableProcessWindowsGhosting(), but it's not recommended.

(MSDN link and highlighted color added by me.)

Also, see KB934228: A transparent layered window appears corrupted after the program stops responding, ...in Windows Vista

Google is my friend.

;)

Edited by PsaltyDS
Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Any idea how to close an individual process that has one of these ghost windows open?

Say we have several programs that have a ghost window open, we want only to end the process Abc.exe when it has a ghost window, not all of them.

Link to comment
Share on other sites

Hi!

$windows=WinList("[CLASS:Ghost]")
$pid=ProcessExists("abc.exe")

For $i=0 To Ubound($windows)-1
    If WinGetProcess($windows[$i][1])=$pid Then
        ProcessClose($pid)
        ExitLoop
    EndIf
Next

;)

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Hi!

$windows=WinList("[CLASS:Ghost]")
$pid=ProcessExists("abc.exe")

For $i=0 To Ubound($windows)-1
    If WinGetProcess($windows[$i][1])=$pid Then
        ProcessClose($pid)
        ExitLoop
    EndIf
Next

;)

@monoceres: No, you missed the point. The Ghost class window belongs to the window manager, not the process that hung. There is likely a way to get the hung process ID, but it has nothing to do with the Ghost window.

@Shaitani: Several Ghost windows...? ;)

What kind of boogered up environment are you running?

:D

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

@monoceres: No, you missed the point. The Ghost class window belongs to the window manager, not the process that hung. There is likely a way to get the hung process ID, but it has nothing to do with the Ghost window.

Of course, how stupid of me Posted Image

I guess you could use SendMessageTimeout to see for yourself if a window is hung...

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Ooh, nice one! :D

Worth repeating here:

; finding a "hung" process
; author gafrost

$v_ret = DllCall("user32.dll","int","IsHungAppWindow", "hwnd", $hwnd)
If $v_ret[0] Then MsgBox(0,"HungApp", "Application is Hung")
 
;.... need to know the handle ( $hwnd )
MSDN article on IsHungAppWindow: IsHungAppWindow Function

Where it says:

You call the IsHungAppWindow function to determine if Microsoft Windows considers that a specified application is not responding. An application is considered to be not responding if it is not waiting for input, is not in startup processing, and has not called PeekMessage within the internal timeout period of 5 seconds.

And for return value:

Returns TRUE if the window stops responding, otherwise returns FALSE. Ghost windows always return TRUE.

So you have to remember to pass it the HWND of an app window, not the ghost window.

;)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

This was a very good suggestion. It seems to have worked perfectly. In summary: instead of checking for the CLASS of a hung window to be 'Ghost', I should use the windows API to have it determine whether the window is actually hung. My side script can then kill the process.

What kind of boogered up environment are you running?

I'm automating the use of some very buggy tools. This information is definitely good to know for future use though, I have a feeling polling hung windows can apply to all sorts of situations.

For those curious, here is exactly what my helper script does now:

While 1

   $hwnd = WinGetHandle("Abc")
   $ret = DllCall("user32.dll","int","IsHungAppWindow", "hwnd", $hwnd)
  
   If (NOT ($hwnd == "") and (@error == 0) and ($ret[0] == 1)) Then
      RunWait(@ComSpec & " /c taskkill /PID " & ProcessExists("abc.exe") & " /F")
   EndIf
   Sleep(5000)

WEnd

Yes, I'm murdering the process, but it was asking for it =).

Thanks for the help guys.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...