Shaitani Posted August 27, 2008 Share Posted August 27, 2008 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 More sharing options...
burners Posted August 27, 2008 Share Posted August 27, 2008 is the window associated to a process? You could do if WinExists("[CLASS:Ghost]") then process close PID wend ~~--Feel Free to Steal my Sigs --~~FLAT LOOK____________________________________ROUNDED LOOK Link to comment Share on other sites More sharing options...
Shaitani Posted August 27, 2008 Author Share Posted August 27, 2008 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 More sharing options...
PsaltyDS Posted August 27, 2008 Share Posted August 27, 2008 (edited) From: The Old New Thing, Friday, January 23, 2004 12:39 PM by Ian HanschenThis 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 VistaGoogle is my friend. Edited August 27, 2008 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 More sharing options...
Shaitani Posted August 27, 2008 Author Share Posted August 27, 2008 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 More sharing options...
monoceres Posted August 27, 2008 Share Posted August 27, 2008 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 More sharing options...
PsaltyDS Posted August 27, 2008 Share Posted August 27, 2008 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? 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 More sharing options...
monoceres Posted August 27, 2008 Share Posted August 27, 2008 @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 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 More sharing options...
Pain Posted August 27, 2008 Share Posted August 27, 2008 you can always give this one a try http://www.autoitscript.com/forum/index.ph...mp;#entry186784 Link to comment Share on other sites More sharing options...
PsaltyDS Posted August 27, 2008 Share Posted August 27, 2008 you can always give this one a try http://www.autoitscript.com/forum/index.ph...mp;#entry186784 Ooh, nice one! 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 More sharing options...
Shaitani Posted August 27, 2008 Author Share Posted August 27, 2008 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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now