OnEvent SRT enhancement
Moderators: Dorian (MJT support), JRL
OnEvent SRT enhancement
This post discusses problem with OnEvent SRT's calling other SRT's:
http://www.mjtnet.com/usergroup/viewtopic.php?t=5331
Can the OnEvent SRT be enhanced so the OnEvent remains disabled until the SRT returns control? Calling another SRT is NOT returning control.
As mentioned in the other post, if the SRT or a nested SRT contains a GoTo statement, the SRT may not be able to return control. So the enhancement would need a way to handle this, probably a system variable the user sets based on a knowledge of whether downstream GoTo's exist.
Please respond whether you think this is doable and good suggestion
Thanks,
Gale
http://www.mjtnet.com/usergroup/viewtopic.php?t=5331
Can the OnEvent SRT be enhanced so the OnEvent remains disabled until the SRT returns control? Calling another SRT is NOT returning control.
As mentioned in the other post, if the SRT or a nested SRT contains a GoTo statement, the SRT may not be able to return control. So the enhancement would need a way to handle this, probably a system variable the user sets based on a knowledge of whether downstream GoTo's exist.
Please respond whether you think this is doable and good suggestion
Thanks,
Gale
- Marcus Tettmar
- Site Admin
- Posts: 7394
- Joined: Thu Sep 19, 2002 3:00 pm
- Location: Dorset, UK
- Contact:
I agree that control should only return when the End of the called subroutine is reached. So I agree it sounds like there's a bug. We'll get that looked at.
I'm not convinced that it should be possible to override this, but as long as it's not the default it probably won't do any harm - something that advanced users who understand the implications can use.
I'm not convinced that it should be possible to override this, but as long as it's not the default it probably won't do any harm - something that advanced users who understand the implications can use.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar
Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar
Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?
Thanks Marcus for looking at this... and thanks Gale for posting about it.mtettmar wrote:I agree that control should only return when the End of the called subroutine is reached. So I agree it sounds like there's a bug. We'll get that looked at.
After trying a few things, I ran into something puzzling to me. Let's say we establish an event handler like this:
OnEvent>WINDOW_OPEN,App_Title,2,Do_App_Open
- I thought that when the targeted window opened, the event handler would fire, execution would pass to our subroutine where we'd handle the event and when execution returned from the subroutine... the event would be over and we'd be done (with that occurance of the event).
- I didn't expect the event handler to fire again until the next time another different (as in different handle) target window actually OPENED (was instantiated).
- Instead, the event seems to keep firing continually WHILE one or more of the target windows are open... try the code below:
Code: Select all
Let>App_Title=Untitled - Notepad
//this var counts the number of times the WINDOW_OPEN event fires
//it should be equal to the number of times you OPEN the App window
Let>window_open_event_count=0
//this var counts the number of times the WINDOW_NOTOPEN event fires
//it should be equal to the number of times you CLOSE the App window
Let>window_closed_event_count=0
//2 in the OnEvent lines below means WF_TYPE=2 - Visible Windows Only
OnEvent>WINDOW_OPEN,App_Title,2,Do_App_Open
OnEvent>WINDOW_NOTOPEN,App_Title,2,Do_App_Not_Open
Label>start
Wait>0.5
Goto>start
SRT>Do_App_Open
Add>window_open_event_count,1
Message>%App_Title% is open%CRLF%window_open_event_count=%window_open_event_count%%CRLF%window_closed_event_count=%window_closed_event_count%
END>Do_App_Open
SRT>Do_App_Not_Open
Add>window_closed_event_count,1
Message>%App_Title% is open%CRLF%window_open_event_count=%window_open_event_count%%CRLF%window_closed_event_count=%window_closed_event_count%
END>Do_App_Not_Open
Last edited by jpuziano on Wed Mar 04, 2009 6:46 am, edited 5 times in total.
jpuziano
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
- Marcus Tettmar
- Site Admin
- Posts: 7394
- Joined: Thu Sep 19, 2002 3:00 pm
- Location: Dorset, UK
- Contact:
That's correct. The event fires when the window is visible. So if its always visible it will always fire. It's up to you how you handle that - often its used to close the window. Or set a flag to indicate whether or not the window has already been spied.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar
Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar
Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?
jpuziano,
For your convenience, here is your script with the event triggers controlled by variable flags.
Window_Open_Flag
Window_Closed_Flag
I've highlighted the additions. To do that I "Quoted" the text. To select and copy the code go all the way to the text area at the bottom.
For your convenience, here is your script with the event triggers controlled by variable flags.
Window_Open_Flag
Window_Closed_Flag
I've highlighted the additions. To do that I "Quoted" the text. To select and copy the code go all the way to the text area at the bottom.
Let>App_Title=Untitled - Notepad
//this var counts the number of times the WINDOW_OPEN event fires
//it should be equal to the number of times you OPEN the App window
Let>window_open_event_count=0
//this var handles the application of the Window_Open event trigger
Let>Window_Open_Flag=0
//this var counts the number of times the WINDOW_NOTOPEN event fires
//it should be equal to the number of times you CLOSE the App window
Let>window_closed_event_count=0
//this var handles the application of the Window_Closed event trigger
Let>Window_Closed_Flag=0
//2 in the OnEvent lines below means WF_TYPE=2 - Visible Windows Only
OnEvent>WINDOW_OPEN,App_Title,2,Do_App_Open
OnEvent>WINDOW_NOTOPEN,App_Title,2,Do_App_Not_Open
Label>start
Wait>0.5
Goto>start
SRT>Do_App_Open
If>Window_Open_Flag>0,Skip_App_Open
Let>Window_Closed_Flag=0
Let>Window_Open_Flag=1
Add>window_open_event_count,1
Message>%App_Title% is
open%CRLF%window_open_event_count=%window_open_event_count%
%CRLF%window_closed_event_count=%window_closed_event_count%
Label>Skip_App_Open
END>Do_App_Open
SRT>Do_App_Not_Open
If>Window_Closed_Flag>0,Skip_App_Not_Open
Let>Window_Open_Flag=0
Let>Window_Closed_Flag=1
Add>window_closed_event_count,1
Message>%App_Title% is not
open%CRLF%window_open_event_count=%window_open_event_count%
%CRLF%window_closed_event_count=%window_closed_event_count%
Label>Skip_App_Not_Open
END>Do_App_Not_Open
Code: Select all
Let>App_Title=Untitled - Notepad
//this var counts the number of times the WINDOW_OPEN event fires
//it should be equal to the number of times you OPEN the App window
Let>window_open_event_count=0
//this var handles the application of the Window_Open event trigger
Let>Window_Open_Flag=0
//this var counts the number of times the WINDOW_NOTOPEN event fires
//it should be equal to the number of times you CLOSE the App window
Let>window_closed_event_count=0
//this var handles the application of the Window_Closed event trigger
Let>Window_Closed_Flag=0
//2 in the OnEvent lines below means WF_TYPE=2 - Visible Windows Only
OnEvent>WINDOW_OPEN,App_Title,2,Do_App_Open
OnEvent>WINDOW_NOTOPEN,App_Title,2,Do_App_Not_Open
Label>start
Wait>0.5
Goto>start
SRT>Do_App_Open
If>Window_Open_Flag>0,Skip_App_Open
Let>Window_Closed_Flag=0
Let>Window_Open_Flag=1
Add>window_open_event_count,1
Message>%App_Title% is open%CRLF%window_open_event_count=%window_open_event_count%%CRLF%window_closed_event_count=%window_closed_event_count%
Label>Skip_App_Open
END>Do_App_Open
SRT>Do_App_Not_Open
If>Window_Closed_Flag>0,Skip_App_Not_Open
Let>Window_Open_Flag=0
Let>Window_Closed_Flag=1
Add>window_closed_event_count,1
Message>%App_Title% is not open%CRLF%window_open_event_count=%window_open_event_count%%CRLF%window_closed_event_count=%window_closed_event_count%
Label>Skip_App_Not_Open
END>Do_App_Not_Open
Hi JRL,
A sense of déjà vu is telling me I've raised this topic before... and the reply from Marcus confirms that the OnEvent> commands were designed this way... i.e. while the target window is open, the OnEvent> handler will keep firing continually and you must handle that with flags.
And you did... thanks for those mods JRL, but try this:
- get the macro (your modified version) running
- open notepad
- Message> shows window_open_event_count=1 (so far so good)
- open a second copy of notepad
- Message> shows window_open_event_count=1 (it didn't see the second one)
- what now?
I am just trying to keep a running count of:
- how many times a certain app window was instantiated
- how many times a certain app window was closed
Since the title of a Notepad window can change if a file has been saved, let's simplify by looking for Calc.exe instead... so change the first line to:
Let>App_Title=Calculator
It should handle multiple copies of the same window title... i.e. once the macro is running... if 10 Calculator apps open and 3 close, I need it to read 10 and 3.
Also, if one or more pre-existing Calculator apps are already open when the macro starts, they should be ignored with respect to the open count because the macro did not "see" them open. Conversely, if one of them is later closed, that should add to the close count because the macro did "see" it close.
A sense of déjà vu is telling me I've raised this topic before... and the reply from Marcus confirms that the OnEvent> commands were designed this way... i.e. while the target window is open, the OnEvent> handler will keep firing continually and you must handle that with flags.
And you did... thanks for those mods JRL, but try this:
- get the macro (your modified version) running
- open notepad
- Message> shows window_open_event_count=1 (so far so good)
- open a second copy of notepad
- Message> shows window_open_event_count=1 (it didn't see the second one)
- what now?
I am just trying to keep a running count of:
- how many times a certain app window was instantiated
- how many times a certain app window was closed
Since the title of a Notepad window can change if a file has been saved, let's simplify by looking for Calc.exe instead... so change the first line to:
Let>App_Title=Calculator
It should handle multiple copies of the same window title... i.e. once the macro is running... if 10 Calculator apps open and 3 close, I need it to read 10 and 3.
Also, if one or more pre-existing Calculator apps are already open when the macro starts, they should be ignored with respect to the open count because the macro did not "see" them open. Conversely, if one of them is later closed, that should add to the close count because the macro did "see" it close.
Last edited by jpuziano on Thu Mar 05, 2009 3:23 pm, edited 3 times in total.
jpuziano
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
- Bob Hansen
- Automation Wizard
- Posts: 2475
- Joined: Tue Sep 24, 2002 3:47 am
- Location: Salem, New Hampshire, US
- Contact:
For jpuziano:
Another approach: How about using pslist and just looping and looking at the PID and incrementing a counter if the values change? Could use pslist>file and then use RegEx on the file to grab the PIDs, compare them to last harvest ID. If multiple instances are open, you will see a PID for each one.I am trying to keep a running count of:
- how many times a certain app window was instantiated
- how many times a certain app window was closed
Hope this was helpful..................good luck,
Bob
A humble man and PROUD of it!
Bob
A humble man and PROUD of it!
Thanks Bob, I hadn't thought of that.Bob Hansen wrote:Another approach: How about using pslist and just looping and looking at the PID and incrementing a counter if the values change? Could use pslist>file and then use RegEx on the file to grab the PIDs, compare them to last harvest ID. If multiple instances are open, you will see a PID for each one.
One problem with that approach might be, if the app is opened and immediately closed, that pid is not around for very long and may not be seen at all. To counter that, I'd have to be checking very aggressively, maybe constantly... and I'd rather avoid that if possible so I'd still like to know if its possible to do this using OnEvent.
Last edited by jpuziano on Thu Mar 05, 2009 3:22 pm, edited 2 times in total.
jpuziano
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
- Bob Hansen
- Automation Wizard
- Posts: 2475
- Joined: Tue Sep 24, 2002 3:47 am
- Location: Salem, New Hampshire, US
- Contact:
Thinking about your problem .......
I am not familiar with Windows Script Host (WSH), but I suspect a script could be written that could access triggers like WhenWindowLoads or WhenWindowUnloads vs. the triggers we have now WhileWindowIsOpen/Closed.
If not WSH, there has to be another language to do that. Don't think VBS has the tools, but VB might, and you could just call a vbs script.
AutoIt may also have the event triggers that you need.
How about two short macros, each using triggers from the Scheduler WhenWindowOpens/Closes. Scripts just increment an INI Opened/Closed counter and closes the macro, waiting for next trigger. These are the triggers you want to put in your script, so just use them to trigger the smaller macros.
I am not familiar with Windows Script Host (WSH), but I suspect a script could be written that could access triggers like WhenWindowLoads or WhenWindowUnloads vs. the triggers we have now WhileWindowIsOpen/Closed.
If not WSH, there has to be another language to do that. Don't think VBS has the tools, but VB might, and you could just call a vbs script.
AutoIt may also have the event triggers that you need.
How about two short macros, each using triggers from the Scheduler WhenWindowOpens/Closes. Scripts just increment an INI Opened/Closed counter and closes the macro, waiting for next trigger. These are the triggers you want to put in your script, so just use them to trigger the smaller macros.
Hope this was helpful..................good luck,
Bob
A humble man and PROUD of it!
Bob
A humble man and PROUD of it!
Hi Bob,
Thanks for the pointers... I appreciate the help.
- the WindowActivate event
- the WindowDeactivate event
- or possibly the WindowDestroy event
I am not sure if an event handler could be written in VBScript to deal with those events.
Setting up the triggers involves setting up Windows Hooks using the SetWindowsHookEx and UnhookWindowsHookEx Win32 API calls.
The article below is all about exactly what I'm trying to do:
Thanks for your help so far Bob and JRL... and if anyone else sees a method, please let me know.
P.S. to gdyvig the original poster... sorry for apparently hijacking this thread Gale, not my intention.
Good luck with your enhancement request for: GOTO_CONSTRAINT new system variable
Thanks for the pointers... I appreciate the help.
I did some Googling on this and found out that I would need to be able to set a trigger on:Bob Hansen wrote:I am not familiar with Windows Script Host (WSH), but I suspect a script could be written that could access triggers like WhenWindowLoads or WhenWindowUnloads vs. the triggers we have now WhileWindowIsOpen/Closed.
If not WSH, there has to be another language to do that. Don't think VBS has the tools, but VB might, and you could just call a vbs script.
- the WindowActivate event
- the WindowDeactivate event
- or possibly the WindowDestroy event
I am not sure if an event handler could be written in VBScript to deal with those events.
Setting up the triggers involves setting up Windows Hooks using the SetWindowsHookEx and UnhookWindowsHookEx Win32 API calls.
The article below is all about exactly what I'm trying to do:
Again, unsure if the above could be translated to VBScript that could be run from inside a marco.Cutting Edge - Windows Hooks in the .NET Framework wrote:http://msdn.microsoft.com/en-ca/magazine/cc188966.aspx
All the key source code available with this article is written in C# but, again, thanks to the language neutrality of the .NET Framework you can easily use Visual Basic .NET to build new hook classes or consumer applications. The sample application is also available in Visual Basic .NET.
I looked, no system OnEvent function for that... perhaps a UDF but couldn't find one.Bob Hansen wrote: AutoIt may also have the event triggers that you need.
I'm not sure I understand what you mean... I get the "increment an INI Opened/Closed counter" part... but how would I deal with the fact that I could have 5 target windows open at the same time now... then one gets closed so I need to increment my closed counter... but since there are still 4 open, only OnEvent>WINDOW_OPEN is firing... continually. How do I "see" the one window being closed if OnEvent>WINDOW_NOTOPEN won't even fire?Bob Hansen wrote: How about two short macros, each using triggers from the Scheduler WhenWindowOpens/Closes. Scripts just increment an INI Opened/Closed counter and closes the macro, waiting for next trigger. These are the triggers you want to put in your script, so just use them to trigger the smaller macros.
Thanks for your help so far Bob and JRL... and if anyone else sees a method, please let me know.
P.S. to gdyvig the original poster... sorry for apparently hijacking this thread Gale, not my intention.
Good luck with your enhancement request for: GOTO_CONSTRAINT new system variable
Last edited by jpuziano on Thu Mar 05, 2009 3:21 pm, edited 1 time in total.
jpuziano
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
You could use the code you already have and add some functionality using tools you already know. Create and maintain either a list or an array of Notepad window handles. Each loop checks to make sure all the windows are open, if one drops out, rewrite the list or reorder the array and report the current count. If a new one starts up, rewrite the list or the array and report.
Your Window_Closed OnEvent will remain pretty much the same, its only going to detect that no Notepads are open. Your Window_Open OnEvent will have more to do, checking and maintaining the list.
Yes, your Window_Open OnEvent will be firing all the time... but the only time it will do any work is when there is a change in Notepad windows count. Otherwise you will be adding a couple hundred thousandths of a second to each loop cycle. Hardly noticeable.
Or (probably easier) you could drop the Onevents and use the "IsProcessRunning" portion of this VBScript that Marcus provided, Run a process. Kill & restart if it runs too long Each time it runs it will tell you how many NotePad windows are open.
Your Window_Closed OnEvent will remain pretty much the same, its only going to detect that no Notepads are open. Your Window_Open OnEvent will have more to do, checking and maintaining the list.
Yes, your Window_Open OnEvent will be firing all the time... but the only time it will do any work is when there is a change in Notepad windows count. Otherwise you will be adding a couple hundred thousandths of a second to each loop cycle. Hardly noticeable.
Or (probably easier) you could drop the Onevents and use the "IsProcessRunning" portion of this VBScript that Marcus provided, Run a process. Kill & restart if it runs too long Each time it runs it will tell you how many NotePad windows are open.
WINDOW_OPEN vs WINDOW_NOTOPEN
If the WINDOW_OPEN OnEvent detects one of many instances of a window it should be responsible for closing that instance, which would be the currently active window. It could verify that it's instance was closed by checking the window handle. Then another WINDOW_OPEN OnEvent would fire on the next instance of that window, which should be the next currently active window.
If WINDOW_OPEN OnEvent detects many instances of a window all having the same title but different in some other way, the SRT would need to examine all instances to determine which one(s) it wants to act on, assuming that instance can be brought into focus. Otherwise an enhancement to OnEvent would be required to check for multiple window properties (WINDOW_OPEN plus class, position, height, width, owner, etc).
The WINDOW_NOTOPEN OnEvent would best be used IMO for cases where a required window other than the one the macro is currently acting on could close at any time in the script.
Gale
If WINDOW_OPEN OnEvent detects many instances of a window all having the same title but different in some other way, the SRT would need to examine all instances to determine which one(s) it wants to act on, assuming that instance can be brought into focus. Otherwise an enhancement to OnEvent would be required to check for multiple window properties (WINDOW_OPEN plus class, position, height, width, owner, etc).
The WINDOW_NOTOPEN OnEvent would best be used IMO for cases where a required window other than the one the macro is currently acting on could close at any time in the script.
Gale
OK, back to notepad windows... The first thing I need to do when the macro starts is to find all the windows that are currently open and if there are any Notepad windows, I would need to get their handles and add them to my list of Notepad window handles. Later, if one of them disappears, I know that the window closed and I can increment a counter. Here's where I started:JRL wrote: You could use the code you already have and add some functionality using tools you already know. Create and maintain either a list or an array of Notepad window handles. Each loop checks to make sure all the windows are open, if one drops out, rewrite the list or reorder the array and report the current count. If a new one starts up, rewrite the list or the array and report.
GetWindowList>winlist
That gives me a list of open top-level windows. Since the list is CRLF delimited, it also shows nicely in an MDL>
So three Notepad windows are already open and I need their handles. Problem is, I can't play around with changing the focus to this window or that to get a handle... and I certainly can't just grab the first one, get handle, close the window, get the next and repeat. This has to happen in the background without affecting what the user sees.MDL>winlist wrote:Macro - GetWindowList
Macro Scheduler 11
Windows Scripting, Windows Macro Automation, Windows Macro Recorder - Automate your PC for Wind - Microsoft Internet Explorer p
Macro Scheduler
Untitled - Notepad
Untitled - Notepad
Untitled - Notepad
Inbox - Microsoft Outlook
Program Manager
Any ideas? Anyone?
Possible enhancement request: Perhaps the GetWindowList> command could be enhanced to have a second mode... that would return a list of window title / window handle pairs.
Last edited by jpuziano on Thu Mar 05, 2009 3:19 pm, edited 1 time in total.
jpuziano
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
jpuziano wrote:So three Notepad windows are already open and I need their handles.
Problem is, I can't play around with changing the focus to this window
or that to get a handle... and I certainly can't just grab the first
one, get handle, close the window, get the next and repeat. This has to
happen in the background without affecting what the user sees.
Any ideas? Anyone?
Help wrote:GetWindowHandle>window_title,handle
Returns the window handle of the window specified by it's window title
- Bob Hansen
- Automation Wizard
- Posts: 2475
- Joined: Tue Sep 24, 2002 3:47 am
- Location: Salem, New Hampshire, US
- Contact:
Does this help?
A combination of these commands:
GetWindowList
GetWindowHandle
GetWindowProcess
RegEx
I thought this might work but I get the same info for all three windows. I missed something somewhere. Cannot dig into it right now, got ot get back to work .... maybe later....
Think it has to do with missing WIN_USEHANDLE=1
A combination of these commands:
GetWindowList
GetWindowHandle
GetWindowProcess
RegEx
Code: Select all
//==================================
// Forum 3/3/09
// How to get list of Window IDs
//Test with three copies of Calculator open
// Messages for testing steps of process only, not needed in final.
Input>vWindowName,What Window are you checking for?,Calculator
GetWindowList>vWindowsList
RegEx>%vWindowName%,%vWindowsList%,0,vWindow,vMatchCount,0
Let>vCount=0
Label>Loop1
Let>vCount=%vCount%+1
Let>vWindow=vWindow_%vCount%
// MessageModal>Window %vCount% is %vWindow%
GetWindowHandle>%vWindow%,vHandle
// MessageModal>Handle %vCount% is %vHandle%
GetWindowProcess>%vWindow%,vPID,vProcess
// MessageModal>Process %vCount% info is are %vPID% - %vProcess%
// MessageModal>Window %vCount% is PID: %vPID% - Process: %vProcess% - Window: %vWindow% - Handle: %vHandle%
Let>vDetails=Window %vCount% is PID: %vPID% - Process: %vProcess% - Window: %vWindow% - Handle: %vHandle%
WriteLn>ProcessList.txt,vResult,%vDetails%
ReadFile>ProcessList.txt,vAnswer
If>%vCount%<vMatchCount>%vAnswer%
DeleteFile>ProcessList.txt
Think it has to do with missing WIN_USEHANDLE=1
Hope this was helpful..................good luck,
Bob
A humble man and PROUD of it!
Bob
A humble man and PROUD of it!