tphiau Posted January 21, 2006 Share Posted January 21, 2006 I am trying to write a script to close (as in WinClose, not terminate) dragon naturally speaking. Unfortunately, this program doesn't have a window, so it doesn't have a window title. I can do this: $PID = ProcessExists("natspeak.exe") If $PID Then ProcessClose($PID) But I would rather let dragon close - thereby saving its user files. Can anyone point me in a useful direction? I thought this might be easy - and maybe it is. Cheerio tony Link to comment Share on other sites More sharing options...
MHz Posted January 21, 2006 Share Posted January 21, 2006 Welcome tphiau,It should have a hidden window that maybe suitable to close. I normally use WinLister from Nirsoft for detecting these hidden windows. Link to comment Share on other sites More sharing options...
TX turtle Posted January 21, 2006 Share Posted January 21, 2006 I'm in a similiar boat. I am interacting with the first window for my company's time sheet app. Program is called TimeTrak. When launched a titleless, borderless window comes up (just like a spash screen). On it are four buttons. I've managed to get it working by using the text on a button ControlClick ( "" , "TimeTrak" , "Button2" ) If it doesn't have a hidden window (TimeTrak doesn't) then I'd recomend setting the WinDetectHiddenText option and trying WinClose ( "" , "Naturally Speaking Hidden Text") ~~Tony Link to comment Share on other sites More sharing options...
Confuzzled Posted January 21, 2006 Share Posted January 21, 2006 Could you play a 'wav' file that has the spoken words to save and exit?eg: Command, Menu, File, Save, OK, Menu, File, Exit (I'm not sure what the commands are)Speech-Recognition Demo: At a recent Sacramento PC User's Group meeting, a company was demonstrating its latest speech-recognition software. A representative from the company was just about ready to start the demonstration and asked everyone in the room to quiet down. Just then someone in the back of the room yelled, "Format C: Return." Someone else chimed in: "Yes, Return". Unfortunately, the software worked. Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted January 21, 2006 Moderators Share Posted January 21, 2006 (edited) In the AutoInfo Tool, under the Title... does the window have a Class? If it does, you could try something like: Opt('WinTitleMatchMode', 4) $Class = 'Text Under Where Title Normally is for the "Class"' WinClose('classname=' & $Class); Or WinKill() If this is a child window, be sure to check if it is NOT the same as the window you want to leave open. Edit: I had a few minutes to try and figure out a solution for you guys... maybe this will help:expandcollapse popup$PID = ProcessExists('My.exe') $Text = 'Put the text of the window you absolutely want to keep here' $aNarray = FindAllWindowsForApp($PID, $Text); This will create an array of all the windows that my executable has open KillMyWindows($aNarray); off to kill the unwanted windows Func FindAllWindowsForApp($az_PID, $t_TextToAvoid) Local $az_WindowPID Local $gz_GetWinList Local $gt_GotWinList = WinList() For $i = 1 To $gt_GotWinList[0][0] $az_WindowPID = WinGetProcess($gt_GotWinList[$i][0]) If $az_WindowPID = $az_PID And StringInStr($gt_GotWinList[$i][0], $t_TextToAvoid) = 0 Then $gz_GetWinList = $gz_GetWinList & FindClassName($gt_GotWinList[$i][1]) & Chr(01)&Chr(01) EndIf Next Return StringSplit(StringTrimRight($gz_GetWinList, 2), Chr(01)&Chr(01)) EndFunc Func FindClassName($hwnd) Local $class = DllCall("user32.dll", "int", "GetClassName", "hwnd", $hwnd, "str", "", "int", 32768) If Not @error Then Return $class[2] EndFunc Func KillMyWindows($aNarray) Local $OPT = Opt('WinTitleMatchMode', 4) Local $OK = 0 For $i = 1 To UBound($aNarray) - 1 If StringInStr($aNarray[$i], '#32770') And $OK = 0 Then $WinMsgBox = MsgBox(4, 'Common Class', '#32270 is a Common Class for Many Windows' _ & @CRLF & 'Accepting to kill this window may kill un-wanted windows' _ & @CRLF & 'Would you like to continue to kill this window?') If $WinMsgBox = 6 Then WinKill('classname=' & $aNarray[$i]) $OK = 1 Else ContinueLoop EndIf Else WinKill('classname=' & $aNarray[$i]) EndIf Next Opt('WinTitleMatchMode', $OPT) EndFunc We are getting the PID of the Executable that we are running, then we are searching for all windows under that PID, then we are getting the 'Class' of each PID, then we will loop thru each class using my before mentioned suggestion of 'classname=' and kill the window we don't want. I'm not 100% sure this will work for you... but give it a try... I'd like to hear if it does. Edited January 21, 2006 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted January 21, 2006 Moderators Share Posted January 21, 2006 (edited) Just for reference... for 'My.exe'... Be sure to put the executable name of the application you're trying to close the window on. Edit: Boredom over took once again! expandcollapse popup#include <guiconstants.au3> #include <Array.au3> $MainGui = GUICreate('Kill A Window', 300, 150) $Lab1 = GUICtrlCreateLabel('Choose your .exe from the Process List', 50, 10, 200, 20) $Com1 = GUICtrlCreateCombo('', 10, 30, 280, 65) $Lab2 = GUICtrlCreateLabel('Is there a window you would like to keep?', 50, 60, 200, 20) $Com2 = GUICtrlCreateCombo('*\*/*\*/*\*/*\*/*\*/*\*', 10, 80, 280, 65) $But1 = GUICtrlCreateButton('Populate Exe', 10, 110, 75, 30) $But2 = GUICtrlCreateButton('Populate Win', 90, 110, 75, 30) $But3 = GUICtrlCreateButton('Execute', 170, 110, 60, 30) $But4 = GUICtrlCreateButton('Clear All', 235, 110, 60, 30) GUISetState() While 1 $Msg = GUIGetMsg() Select Case $Msg = - 3 Exit Case $Msg = $But1 GUICtrlSetData($Com1, '') GUICtrlSetData($Com1, GetProcessList()) Case $Msg = $But2 GUICtrlSetData($Com2, '', '*\*/*\*/*\*/*\*/*\*/*\*') GUICtrlSetData($Com2, FindAllWindowsForApp(ProcessExists(GUICtrlRead($Com1))), '*\*/*\*/*\*/*\*/*\*/*\*') Case $Msg = $But3 Local $nArray = WindowsToClass(ProcessExists(GUICtrlRead($Com1)), GUICtrlRead($Com2)) KillMyWindows($nArray) Case $Msg = $But4 GUICtrlSetData($Com1, '') GUICtrlSetData($Com2, '') EndSelect WEnd Func WindowsToClass($az_PID, $WinToKeep) Local $az_WindowPID Local $gz_GetWinList Local $gt_GotWinList = WinList() For $i = 1 To $gt_GotWinList[0][0] $az_WindowPID = WinGetProcess($gt_GotWinList[$i][0]) If $az_WindowPID = $az_PID And StringInStr($gt_GotWinList[$i][0], $WinToKeep) = 0 Then $gz_GetWinList = $gz_GetWinList & FindClassName($gt_GotWinList[$i][1]) & Chr(01)&Chr(01) EndIf Next Return StringSplit(StringTrimRight($gz_GetWinList, 2), Chr(01)&Chr(01)) EndFunc Func FindAllWindowsForApp($az_PID) Local $az_WindowPID Local $gz_GetWinList Local $gt_GotWinList = WinList() For $i = 1 To $gt_GotWinList[0][0] $az_WindowPID = WinGetProcess($gt_GotWinList[$i][0]) If $az_WindowPID = $az_PID Then $gz_GetWinList = $gz_GetWinList & $gt_GotWinList[$i][0] & '|' EndIf Next Return $gz_GetWinList & '*\*/*\*/*\*/*\*/*\*/*\*' EndFunc Func FindClassName($hwnd) Local $class = DllCall("user32.dll", "int", "GetClassName", "hwnd", $hwnd, "str", "", "int", 32768) If Not @error Then Return $class[2] EndFunc Func KillMyWindows($aNarray) Local $OPT = Opt('WinTitleMatchMode', 4) Local $OK = 0 For $i = 1 To UBound($aNarray) - 1 If StringInStr($aNarray[$i], '#32770') And $OK = 0 Then $WinMsgBox = MsgBox(4, 'Common Class', '#32270 is a Common Class for Many Windows' _ & @CRLF & 'Accepting to kill this window may kill un-wanted windows' _ & @CRLF & 'Would you like to continue to kill this window?') If $WinMsgBox = 6 Then WinKill('classname=' & $aNarray[$i]) $OK = 1 Else ContinueLoop EndIf Else WinKill('classname=' & $aNarray[$i]) EndIf Next Opt('WinTitleMatchMode', $OPT) EndFunc Func GetProcessList() Local $ProcList = ProcessList() Local $ReturnList = '' For $i = 1 to $ProcList[0][0] $ReturnList = $ReturnList & $ProcList[$i][0] & '|' Next $MakeArray = StringSplit(StringTrimRight($ReturnList, 1), '|') $ReturnList = '' _ArraySort($MakeArray) For $i = 1 To UBound($MakeArray) - 1 $ReturnList = $ReturnList & $MakeArray[$i] & '|' Next Return $ReturnList EndFunc Edited January 21, 2006 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
tphiau Posted January 22, 2006 Author Share Posted January 22, 2006 Wow! Blown away completely by your responses. thanks. So in order, MHz, It took a bit to find a valid download for WinLister. and guess what? When Dragon is running and minimise to the taskbar, Winlister shows nothing. Not until you click on the icon in the taskbar does WinLister show Dragon even exists. But none of them have a title. Confussled, Re playing a command, I'm running other programs that provide ad-ons to Dragon. They all need to be closed down in order. So it might be possible to trick dragon into doing this as you say. I'll dig into that one. SmOke_N, first, thanks for your extended answers. The first thing is, that I don't want to terminate the process. I need dragon to close itself, and save its various files. I tried using VBS to AppActivate it, and then SendKeys. And while I can get the dragon system tray right click menu to popup, it won't take the keys. WinLister gives me a class of #32768 when I pop up the dragon tray icon. I assume that this is not the actual classname though. I haven't yet had a chance to go through your other code. I am not wanting to kill the process. I can do that easily with these two lines: $PID = ProcessExists("natspeak.exe") If $PID Then ProcessClose($PID) Your last codes found the class accurately (#32270), and did terminate the process. Perhaps I can find a way to use the code to determine how to apply it to WinCLose, so I close the program rather than kill it. Thanks a bunch, tony Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted January 22, 2006 Moderators Share Posted January 22, 2006 My script I wrote doesn't terminate the process (unless that is the only window tied to it (the process), or #32270 is the name of both classes... remember, it does make a difference if the window is a child... This is why you have the option to put in 'Text' of the 'Title' of the window you want to keep). Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
MHz Posted January 22, 2006 Share Posted January 22, 2006 Sounds to me that WinLister is only displaying visible windows for you. Go into options in the toolbar and ensure "Display Hidden Windows" is checked and "Display Windows With 0,0 Size" is checked. It should show you the invisible windows of the systray icon and perhaps others. Perhaps not, but I would be very surprised if it did not. Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted January 22, 2006 Moderators Share Posted January 22, 2006 Sounds to me that WinLister is only displaying visible windows for you. Go into options in the toolbar and ensure "Display Hidden Windows" is checked and "Display Windows With 0,0 Size" is checked.It should show you the invisible windows of the systray icon and perhaps others. Perhaps not, but I would be very surprised if it did not.That winlist is a handy tool there MHz, I played with it yesterday!! The script I wrote should do the same thing though for specific applications. Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
tphiau Posted January 22, 2006 Author Share Posted January 22, 2006 Hi SmOke_N, The initial problem is that I don't know what the window title text is. So I'm not sure how to use that as an option. What I notice is that dragon disappears from the taskbar, but doesn't pop up its normal "saving" window. I will test further to see whether it is saving though. MHz, I did as you suggest, and of course, there are quite a number of dragon hidden windows. one is called "natspeak", which is the name of the .exe task in the taskmanager. Another is "Dragon NaturallySpeaking" Neither of these works with Winclose in the following construct though. WinClose("natspeak", "") I'm checking out the WinDetectHiddenText function to see whether this will help here. thanks again. tony Link to comment Share on other sites More sharing options...
tphiau Posted January 22, 2006 Author Share Posted January 22, 2006 OK, I experimented some more. SmOke_N, Your code does seem to Kill (as in terminate) the process. I think these lines do it: WinKill('classname=' & $aNarray[$i]) Of course, being dumb with this, I changed WinKill to WinClose, and while it popped up Dragon's saving box, it screwed Dragon up. Also, because the class is actually 32770, it gets into damaging some other programs (as per your warning). Did I misunderstand this? Cheers, tony Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted January 22, 2006 Moderators Share Posted January 22, 2006 (edited) The winkill is killing the 'window' thus the name. As I said, if it is the only window available, then it may in fact close the process also. My suggestion was this, let's say I have 2 windows. Window one's title is: Learn Something Else Window two's title is: Whatever You run my script: Put in Learn Something Else ... this makes sure that that particualr window will not be killed. But now that I think about it, I'll have to look to see if I passed the window to 'not' kill to the window kill. If not you can do that. Edit: ------------- Nope I didn't pass it... Here try this, this makes double sure it's not killed (the window you want to save): Edit2: I had stuff in the wrong place: expandcollapse popup#include <guiconstants.au3> #include <Array.au3> $MainGui = GUICreate('Kill A Window', 300, 150) $Lab1 = GUICtrlCreateLabel('Choose your .exe from the Process List', 50, 10, 200, 20) $Com1 = GUICtrlCreateCombo('', 10, 30, 280, 65) $Lab2 = GUICtrlCreateLabel('Is there a window you would like to keep?', 50, 60, 200, 20) $Com2 = GUICtrlCreateCombo('*\*/*\*/*\*/*\*/*\*/*\*', 10, 80, 280, 65) $But1 = GUICtrlCreateButton('Populate Exe', 10, 110, 75, 30) $But2 = GUICtrlCreateButton('Populate Win', 90, 110, 75, 30) $But3 = GUICtrlCreateButton('Execute', 170, 110, 60, 30) $But4 = GUICtrlCreateButton('Clear All', 235, 110, 60, 30) GUISetState() While 1 $Msg = GUIGetMsg() Select Case $Msg = - 3 Exit Case $Msg = $But1 GUICtrlSetData($Com1, '') GUICtrlSetData($Com1, GetProcessList()) Case $Msg = $But2 GUICtrlSetData($Com2, '', '*\*/*\*/*\*/*\*/*\*/*\*') GUICtrlSetData($Com2, FindAllWindowsForApp(ProcessExists(GUICtrlRead($Com1))), '*\*/*\*/*\*/*\*/*\*/*\*') Case $Msg = $But3 Local $nArray = WindowsToClass(ProcessExists(GUICtrlRead($Com1)), GUICtrlRead($Com2)) KillMyWindows($nArray, GUICtrlRead($Com2)) Case $Msg = $But4 GUICtrlSetData($Com1, '') GUICtrlSetData($Com2, '') EndSelect WEnd Func WindowsToClass($az_PID, $WinToKeep) Local $az_WindowPID Local $gz_GetWinList Local $gt_GotWinList = WinList() For $i = 1 To $gt_GotWinList[0][0] $az_WindowPID = WinGetProcess($gt_GotWinList[$i][0]) If $az_WindowPID = $az_PID And StringInStr($gt_GotWinList[$i][0], $WinToKeep) = 0 Then $gz_GetWinList = $gz_GetWinList & FindClassName($gt_GotWinList[$i][1]) & Chr(01)&Chr(01) EndIf Next Return StringSplit(StringTrimRight($gz_GetWinList, 2), Chr(01)&Chr(01)) EndFunc Func FindAllWindowsForApp($az_PID) Local $az_WindowPID Local $gz_GetWinList Local $gt_GotWinList = WinList() For $i = 1 To $gt_GotWinList[0][0] $az_WindowPID = WinGetProcess($gt_GotWinList[$i][0]) If $az_WindowPID = $az_PID Then $gz_GetWinList = $gz_GetWinList & $gt_GotWinList[$i][0] & '|' EndIf Next Return $gz_GetWinList & '*\*/*\*/*\*/*\*/*\*/*\*' EndFunc Func FindClassName($hwnd) Local $class = DllCall("user32.dll", "int", "GetClassName", "hwnd", $hwnd, "str", "", "int", 32768) If Not @error Then Return $class[2] EndFunc Func KillMyWindows($aNarray, $DontKill) Local $OPT = Opt('WinTitleMatchMode', 4) Local $OK = 0 For $i = 1 To UBound($aNarray) - 1 If StringInStr($aNarray[$i], '#32770') And $OK = 0 Then $WinMsgBox = MsgBox(4, 'Common Class', '#32270 is a Common Class for Many Windows' _ & @CRLF & 'Accepting to kill this window may kill un-wanted windows' _ & @CRLF & 'Would you like to continue to kill this window?') If $WinMsgBox = 6 Then If StringInStr($aNarray[$i], $DontKill) = 0 Then WinKill('classname=' & $aNarray[$i]) $OK = 1 Else ContinueLoop EndIf ElseIf StringInStr($aNarray[$i], $DontKill) = 0 Then WinKill('classname=' & $aNarray[$i]) EndIf Next Opt('WinTitleMatchMode', $OPT) EndFunc Func GetProcessList() Local $ProcList = ProcessList() Local $ReturnList = '' For $i = 1 to $ProcList[0][0] $ReturnList = $ReturnList & $ProcList[$i][0] & '|' Next $MakeArray = StringSplit(StringTrimRight($ReturnList, 1), '|') $ReturnList = '' _ArraySort($MakeArray) For $i = 1 To UBound($MakeArray) - 1 $ReturnList = $ReturnList & $MakeArray[$i] & '|' Next Return $ReturnList EndFunc Edited January 22, 2006 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
tphiau Posted January 22, 2006 Author Share Posted January 22, 2006 Hi SmOke_N, I understand what your code does. You obviously have a good handle on scripting. I ran your modified version, but didn't chose a dragon window (by selecting its text) to keep. (As in, I don't actually have a need to keep one since I'm trying to close dragon). This time dragon threw up an error screen and dissapeared up its own spout. This is turning out to be more complex than I imagined. thanks, tony Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted January 22, 2006 Moderators Share Posted January 22, 2006 Just wish I had dragon to help you out more... I know it's a huge program, so I won't be downloading it to see what could be done. Hope you get it figured out. Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
tphiau Posted January 23, 2006 Author Share Posted January 23, 2006 (edited) You are never going to belive this... The sweet smell of success! This did it: AutoItSetOption("WinTitleMatchMode", 4) $handle = WinGetHandle("DragonBar", "") WinClose($handle) SmOke_N, I noticed one of your scripts (when I replaced WinKill with WinClose, actually popped up the dragon close sequence, but then freaked out. That got me thinking that one of the processes obvously must do the job. So I used WinLister (thnks MHz), and your script SmOke_N to discover which one. Then just had to figure out how to get hold of it and close it. And the handle was the answer Yahooooooo! (no trademark infringements intended) thanks again, tony Edited January 23, 2006 by tphiau 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