[FIXED] Event Handler firing during VBScript causes error

Technical support and scripting issues

Moderators: Dorian (MJT support), JRL

Post Reply
User avatar
jpuziano
Automation Wizard
Posts: 1086
Joined: Sat Oct 30, 2004 12:00 am

[FIXED] Event Handler firing during VBScript causes error

Post by jpuziano » Sat Jan 29, 2011 8:23 am

Hi Marcus,

Event Handlers are great... but I am running into what looks like a bug or two when they fire while VBScript is executing.

Please try the following script... error shows up when run compiled or not.

Code: Select all

// COMPILE_OPTS|C:\event_handler_firing_during_VBScript_causes_error.exe||CONSOLE=0|INCLUDES=0| /NOSYSTRAY /HIDE

VBSTART

Dim IE

Sub CreateIE(IE_win_position_X,IE_win_position_Y)
  Set IE = CreateObject("InternetExplorer.Application")
  IE.visible = 0

  'Window size and position
  'IE.Left = 217
  IE.Left = IE_win_position_X
  'IE.Top = 0
  IE.Top = IE_win_position_Y
  IE.Height = 652
  IE.Width = 722

  'Comment out the line to leave enabled or set to 0 to Disable
  'IE.MenuBar = 0
  'IE.ToolBar = 0
  IE.AddressBar = 0
  'IE.StatusBar = 0
  'IE.Resizable = 0
End Sub

Sub Navigate(URL)
  IE.navigate URL
End Sub

Sub WaitBusy
  do while IE.Busy
  loop
End Sub

Sub DestroyIE
   IE.Quit
   Set IE = Nothing
End Sub

Sub MakeVisible
  IE.visible = 1
End Sub

VBEND

Dialog>Dialog1
object Dialog1: TForm
  Left = 251
  Top = 97
  HelpContext = 5000
  BorderIcons = [biSystemMenu]
  Caption = 'Main Window'
  ClientHeight = 223
  ClientWidth = 439
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = True
  Position = poScreenCenter
  ShowHint = True
  OnTaskBar = False
  PixelsPerInch = 96
  TextHeight = 13
end
EndDialog>Dialog1

Let>APP_TITLE=MyApp

//initialize X and Y base co-ords of IE windows... this is where window 1 will open
//Let>IE_win_position_base_X=217
Let>IE_win_position_base_X=0
Let>IE_win_position_base_Y=0
//each subsequent IE CLR window will be offset by this ammount
Let>IE_win_position_offset=22
//This is the current positional "slot" that the IE CLR will position at.
//Valid values start at 1 and goes up to IE_win_position_max.
//We initialize at -1 because we'll increment before opening the window
//and we're multiplying the number by the offset value... window
Let>IE_win_position_number=-1
//this is the highest number of positions we'll position at
Let>IE_win_max_window_positions=10

AddTrayIcon>C:\MyIcon.ico,MyTrayIcon,MyApp

//Add System Tray icon Handlers
AddTrayHandler>MyTrayIcon,OnClick,Do_Show_Hide_Main_Window
AddTrayHandler>MyTrayIcon,OnDblClick,Do_Show_Hide_Main_Window

//Pressing ALT+F11 will run the "ACTION" Subroutine
OnEvent>KEY_DOWN,VK122,3,ACTION


SRT>ACTION

  //calculate X and Y values for current IE CLR window positional slot
  Let>IE_win_position_number=IE_win_position_number+1
  If>IE_win_position_number=IE_win_max_window_positions
    //reset if we're at the max, 0 is first slot
    Let>IE_win_position_number=0
  EndIf
  Let>IE_win_position_X={%IE_win_position_base_X%+(%IE_win_position_number%*%IE_win_position_offset%)}
  Let>IE_win_position_Y={%IE_win_position_base_Y%+(%IE_win_position_number%*%IE_win_position_offset%)}

  Let>url=http://www.mjtnet.com/

  //new method below using VBScript and must supply X and Y co-ords to open at
  VBRun>CreateIE,IE_win_position_X,IE_win_position_Y
  VBRun>Navigate,%url%
  VBRun>MakeVisible
  VBRun>WaitBusy

END>ACTION


SRT>Do_Show_Hide_Main_Window

  //if Main Window is visible, set var main_window_visible = True
  GetDialogProperty>Dialog1,,Visible,main_window_visible
  If>main_window_visible=True
    SetDialogProperty>Dialog1,,Visible,False
  EndIf
  If>main_window_visible=True,bypass_and_return

  //if we make it here, Main Window was not visible... so make it visible

  //...for some reason, I have to setfocus on a different window first...
  SetFocus>Program Manager

  SetDialogProperty>Dialog1,,Visible,True
  //...and then I can setfocus on the Main Window
  Wait>0.2
  SetFocus>Main Window

  Label>bypass_and_return

END>Do_Show_Hide_Main_Window

SRT>DoExit
  Exit>0
END>DoExit

Show>Dialog1


//app spends most of its time in this loop... waiting for something to happen
Label>Loop
Wait>0.01
Goto>Loop
For the following line, supply your own icon file so you'll have a systray icon to click:

Code: Select all

AddTrayIcon>C:\MyIcon.ico,MyTrayIcon,MyApp
When you run this, clicking the systray icon will toggle the Main Window from visible to non-visible... that works great.

STEPS TO PRODUCE ERROR:

- Tap ALT+F11 and it will run the ACTION subroutine which uses VBScript calls to open an IE window.

- Immediately after the above step i.e. while the VBScript is still executing, click the systray icon and it will produce the following error...

Code: Select all

---------------------------
Information
---------------------------
Error initializing MSSCRIPT control.
---------------------------
OK   
---------------------------
...click OK on the error... and from then on, any further presses of ALT+F11 will return this second error:

Code: Select all

---------------------------
Information
---------------------------
Line: 114 VBScript Runtimes Are Not Properly Installed
---------------------------
OK   Abort   
---------------------------
You can even halt the macro, run it again and when you press ALT+F11, it does not even try to run the VBScript to open an IE window, it just gives you the second error above.

You must shut down MS itself, then fire it up again and only then will things reset and you can repeat the above results.

Please let me know if you (or anyone) can replicate this... thanks Marcus.

Take care
Last edited by jpuziano on Tue Aug 09, 2011 3:00 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 - :-)

User avatar
Marcus Tettmar
Site Admin
Posts: 7156
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Mon Jan 31, 2011 10:49 am

Couldn't reproduce the first few times, but managed to by acting super fast. It's on the work list.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1086
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Mon Jan 31, 2011 6:39 pm

mtettmar wrote:Couldn't reproduce the first few times, but managed to by acting super fast. It's on the work list.
Great... I'm relieved that you can reproduce this problem.

I was lucky to find it... I was client testing this from the perspective of an impatient user... one who wants to do everything as fast as possible.

Because Event Handlers can fire literally at "any time", they could certainly fire while the main script is busy processing VBScript code and if that happens... the error occurs.

In my example script, you have to be super fast to casue the error because the VBScript code I’m using runs and finishes quickly.

However if the VBScript code I needed to run was larger and took longer, say it took a minute to run and complete... well during that minute while the user is just waiting... they may very well click the systray icon and cause the error.

I love what Event handlers can do for a compiled MS macro but I need the power/convenience of VBScript as well... so I hope you find a solution or workaround to this problem soon.

Thanks and take care
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 - :-)

User avatar
JRL
Automation Wizard
Posts: 3320
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Mon Jan 31, 2011 6:55 pm

Looks to me like a well placed Flag could resolve your issue.

Add at the top of your script:
Let>VBS_Flag=0

Then add in the Do_Show_Hide_Main_Window subroutine
If>VBS_Flag=0

Code: Select all

SRT>Do_Show_Hide_Main_Window
If>VBS_Flag=0
  //if Main Window is visible, set var main_window_visible = True
  GetDialogProperty>Dialog1,,Visible,main_window_visible
  If>main_window_visible=True
    SetDialogProperty>Dialog1,,Visible,False
  EndIf
  If>main_window_visible=True,bypass_and_return

  //if we make it here, Main Window was not visible... so make it visible

  //...for some reason, I have to setfocus on a different window first...
  SetFocus>Program Manager

  SetDialogProperty>Dialog1,,Visible,True
  //...and then I can setfocus on the Main Window
  Wait>0.2
  SetFocus>Main Window

  Label>bypass_and_return
EndIf
END>Do_Show_Hide_Main_Window
Then add in your VBScript calls area
Let>VBS_Flag=1
And at the end of the calls
Let>VBS_Flag=0

Code: Select all

Let>VBS_Flag=1
  VBRun>CreateIE,IE_win_position_X,IE_win_position_Y
  VBRun>Navigate,%url%
  VBRun>MakeVisible
  VBRun>WaitBusy
Let>VBS_Flag=0
By adding the variable Flag to your script, you control when the OnEvent runs its assigned subroutine's process. If the flag value is not zero, the subroutine will do nothing.

User avatar
jpuziano
Automation Wizard
Posts: 1086
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Mon Jan 31, 2011 7:18 pm

JRL wrote:By adding the variable Flag to your script, you control when the OnEvent runs its assigned subroutine's process. If the flag value is not zero, the subroutine will do nothing.
Thanks for that JRL however...

...even if that prevents the error from occuring (and I'm not sure yet that it does)... when the user clicks the systray icon... they EXPECT the main window to appear instantly... if it doesn't, they are going to think that something is broken.

Now maybe (again not sure) a msg could be displayed telling them...

"Sorry, can't display Main Window right now, please wait for VBScript to finish processing..."

...but that is weak and should not be necessary.

In this case... I am looking for a fix from Marcus so that internally, Macro Scheduler can handle this "collision situation" without missing a beat...

...but thanks for your suggestion. I do appreciate the thought you put into coming up with different angles to solve problems... and have benefited greatly over the years from your solutions... but no, in this case, it should just handle this internally... for me in my script... for everyone in whatever scripts they come up with in the future.

Take care
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 - :-)

User avatar
JRL
Automation Wizard
Posts: 3320
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Mon Jan 31, 2011 8:11 pm

In this case... I am looking for a fix from Marcus so that internally, Macro Scheduler can handle this "collision situation" without missing a beat...
I will agree with you IF the fix does not remove or interfere with the current flexibility of event handlers. I'm not an expert by any means but the potential issue I perceive is that if event handlers automatically detect a VBScript for example, and automagically fail to run while the script is running then we have a Macro Scheduler limitation similar to the one now imposed by ALL forms of Wait>.
"Sorry, can't display Main Window right now, please wait for VBScript to finish processing..."
...but that is weak and should not be necessary.
Weak? How is that weak? Maybe the message is weak. Perhaps it should simply say "Please Wait" And when the VBScript has finished performing its duties the user's systray icon click can be acted upon.

Again. I want to emphasize I don't know enough about what can be accomplished by Marcus, to express a definitive opinion. I only want to be certain that we don't make one task easier by limiting future potential.

User avatar
jpuziano
Automation Wizard
Posts: 1086
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Mon Jan 31, 2011 8:21 pm

JRL wrote:I will agree with you IF the fix does not remove or interfere with the current flexibility of event handlers.
Of course... I would not want that either. But bear in mind, this problem with Macro Scheduler Event Handlers... the VBScript collision scenario and resulting error... has probably always existed, its just that no one has run into or reported the problem until now. Now that it has been reported and replicated by Marcus, we can look forward to a fix.
JRL wrote:Again. I want to emphasize I don't know enough about what can be accomplished by Marcus, to express a definitive opinion. I only want to be certain that we don't make one task easier by limiting future potential.
Absolutely... I'm sure no one here wants to limit future potential, I certainly don't. Let's see what Marcus can come up with... maybe a fix is just around the corner.
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 - :-)

User avatar
jpuziano
Automation Wizard
Posts: 1086
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Tue Feb 01, 2011 11:45 pm

Hi JRL and Marcus,
JRL wrote:
jpuziano wrote:In this case... I am looking for a fix from Marcus so that internally, Macro Scheduler can handle this "collision situation" without missing a beat...
I will agree with you IF the fix does not remove or interfere with the current flexibility of event handlers. I'm not an expert by any means but the potential issue I perceive is that if event handlers automatically detect a VBScript for example, and automagically fail to run while the script is running then we have a Macro Scheduler limitation similar to the one now imposed by ALL forms of Wait>.
JRL wrote:
jpuziano wrote:"Sorry, can't display Main Window right now, please wait for VBScript to finish processing..."
...but that is weak and should not be necessary.
Weak? How is that weak? Maybe the message is weak. Perhaps it should simply say "Please Wait" And when the VBScript has finished performing its duties the user's systray icon click can be acted upon.
I will gladly explain why I think having to display such a message is... weak. Please open the Help File and seach for the following text string:
  • all event handlers are now executed instantly
You should find the Help File topic on "Modal vs Non-Modal Dialogs" and in there, it plainly says:
  • all event handlers are now executed instantly
It DOES NOT say:
  • all event handlers are now executed instantly... except if your main script happens to be executing VBScript in which case we'll throw an error message... however if you want to avoid throwing the error, you should do some extra coding to check if maybe your main script is currently executing some VBScript... and if it is... wait until that is done before proceeding with the Event Handler code... oh and you may want to pop up a message to your user telling them they may have to wait until the VBScript code is finished... blah blah blah...
So to my way of thinking, either:

a) this is fixed and Event Handlers truly can execute instantly... even if the main script is running VBScript code at the time...

or

b) this cannot be fixed... so I'd expect all references to how Event Handlers work should mention the potential VBScript collision scenario and perhaps some instructions/tips on how to best handle that.

I hope this is clear. I am not asking for an internal hack to make life easier for me and one script I have written. I am asking for Event Handlers to work... as advertised.

Fair enough?
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 - :-)

User avatar
JRL
Automation Wizard
Posts: 3320
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Wed Feb 02, 2011 6:52 am

When you read the entire paragraph, It seems clear to me that the discussion is exclusively about the AddDialogHandler> function. Although, to be fair, I would concede that since AddDialogHandler did not exist prior to version 12, the wording might lead one to conclude that ALL events are covered as you have stated to be your understanding.
Help for Modal vs Non-Modal Dialogs wrote:A note for existing users: If you are coming from Macro Scheduler prior to version 12 you will find you no longer need to make your dialog non-modal in order to interact with it and modify its properties, as all event handlers are now executed instantly, whether or not the dialog is modal. Prior to v12 the most common reason for making a dialog non-modal was so that you could detect changes on it and update it due to the fact that scripts were executed sequentially. AddDialogHandler creates real time event code that can be executed at the same time as other code and even when the dialog is modal. Therefore in most cases you should find you no longer need non-modal dialogs.
BUT... I don't think this help topic was meant to encompass ALL Event functions. It certainly does not include OnEvent> function calls. If you create and call a modal dialog, during the time that the script is "paused" on the Show>Dialog,res line, OnEvent> function calls will fail.

For example, the following script sample has a key_down OnEvent using the ESC key (VK27) to call a subroutine named "Quit" that will exit the script. If you run this script as written, pressing the Esc key will not stop the script. However, if you remove the "res1" result variable from the Show>Dialog1,res1 line, and run the script, you'll find that pressing the Esc key exits the script.

Code: Select all

OnEvent>key_down,VK27,0,Quit

Dialog>Dialog1
EndDialog>Dialog1

Show>dialog1,res1

Label>Loop
  Wait>0.01
Goto>Loop

SRT>Quit
  Exit>0
END>Quit
This is a similar result for ALL OnEvent> function possibilities. They do not fire if the script is paused for any of a multitude of reasons. Reasons include Modal dialog calls, WaitWindowOpen, WaitWindowClosed, Wait etc., RunProgram with RP_Wait set to 1, CopyFile, MoveFile, VBRun and VBEval. Basically anything that causes script execution to pause while the function's activity works through to its completion.

The reason for this is simple, OnEvent is doing its work between each line of code. A script is a single thread activity and as such the way onevents function is to check for their specified activity while there is not a line of code in play, during that hundred thousandth of a second that separates one line from the next. IF you want an event handler to function independently of the script then create a separate independent script. Something like the following. This is a modal dialog that will be closed by a Esc key press. The Esc key press event is detected by an independent dynamically created script.

Code: Select all

LabelToVar>Event,var
WriteLn>%temp_dir%EscwillCloseDialog.scp,wres,var
ExecuteFile>%temp_dir%EscwillCloseDialog.scp

/*
Event:
OnEvent>key_down,VK27,0,Quit
Label>Loop
  Wait>0.01
Goto>Loop

SRT>Quit
  CloseWindow>Dialog1
  DeleteFile>%temp_dir%EscwillCloseDialog.scp
  Exit>0
END>Quit
*/

Dialog>Dialog1
EndDialog>Dialog1

Show>dialog1,res1
Creating a second independent script that interacts with the main script would probably be the prefered way to handle the AddTrayHandler> event rather than the variable flag method I mentioned earlier. Perhaps Macro Scheduler can be made to accomplish this automatically. I agree it would be nice if ALL events would process no matter whether the script is in some wait state or not. (Though I wonder what new issues that might create) In any case I don't see these solutions as internal hacks or work arounds, I see them as using the software as its currently designed to be used.

Take care and remember whether we agree on individual issues or not we're all in this together. The goal is to be helpful.

User avatar
jpuziano
Automation Wizard
Posts: 1086
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Wed Feb 02, 2011 8:52 am

JRL wrote:BUT... I don't think this help topic was meant to encompass ALL Event functions. It certainly does not include OnEvent> function calls. If you create and call a modal dialog, during the time that the script is "paused" on the Show>Dialog,res line, OnEvent> function calls will fail.
Yes I will give you that... and perhaps I should have said "not including events setup with OnEvent>" because yes I know that those events will not fire while main script execution is stuck at some modal command... but as you can see, my example has no modal commands in it... and my main loop where I wait for things to happen is this...

Code: Select all

//app spends most of its time in this loop... waiting for something to happen
Label>Loop
Wait>0.01
Goto>Loop
...and that Wait value is the smallest it can be... so there is no real halt to the main script... so there is no excuse... even for events setup via an OnEvent> command not to fire.

But that's not a problem because in my example script, when I hit ALT+F11, the event setup by OnEvent> does fire... and when it does, main script execution is directed to the ACTION subroutine that calls the VBScript.

And while the main script is busy executing VBScript, I click the systray icon and the new Event Handler setup by AddTrayHandler> also fires... but the problem is... it errors out *if* the main script still happens to be executing VBScript at that exact moment. Why? What does that error mean? In contrast, it works just fine if the main script is only executing MS commands at the time the Tray Event Handler fires.
JRL wrote:Creating a second independent script that interacts with the main script would probably be the prefered way to handle the AddTrayHandler> event rather than the variable flag method I mentioned earlier.
Even that may be unnecessary as I suspect Marcus is accomplishing this internally... perhaps by creating separate independently executing threads for each new Dialog or SysTray Event Handler created.

At this point, I still consider this Event Handler / VBScript collision scenario that produces an error... a bug that should be fixed. If Marcus does not consider it a bug, then I am open to guidance on how to deal with this in the code... because a user can click a systray icon at any time... and it may well be while the main script is busy executing some VBScript.
JRL wrote:Take care and remember whether we agree on individual issues or not we're all in this together. The goal is to be helpful.
Of course... and I'm glad to encourage further input on this topic from everyone with an interest. Does anyone else out there use the new Dialog and Sys Tray Event Handlers? Do you also use VBScript?

If I can learn ways to use Event Handlers more effectively while still "using the software as its currently designed to be used", then fantastic. But at the same time, if I see something I think may be a bug, I'm going to post about it.

Marcus, if its not a bug... but a technical limitation... please let us know... and please don't think I'm being critical. The new v12 Dialogs and Event Handlers are great and it will probably be a while before many of us learn how to take advantage of what we already have here.

Take care
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 - :-)

User avatar
jpuziano
Automation Wizard
Posts: 1086
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Wed Feb 02, 2011 9:53 pm

JRL wrote:I agree it would be nice if ALL events would process no matter whether the script is in some wait state or not.
It sure would! :D

And hey, if the new v12 Sys Tray event handlers can do it, responding instantly no matter what the main script is doing... then conceivably, OnEvent> could be beefed up to also work the same way... with its own independant thread/s.

Of course, Marcus has yet to weigh in on any of this. Marcus any thoughts... or are we just dreaming?
Last edited by jpuziano on Thu Feb 03, 2011 6:14 am, 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 - :-)

User avatar
jpuziano
Automation Wizard
Posts: 1086
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Thu Feb 03, 2011 6:11 am

Hi JRL,

I modified my original bug demo code below to show the difference between OnEvent> during a Wait>30 and the new Sys Tray event handler. Please run the test code below and let me know your findings. I've added:

- Messages that prompt you to do certain tests during a Wait>30
- A new v12 style dialog event handler for OnClose that should end the macro when you click the X on the main window

You can run this uncompiled, the first line is just there for convienience should you decide to test it compiled as well.

Code: Select all

// COMPILE_OPTS|C:\event_handler_firing_during_VBScript_causes_error.exe||CONSOLE=0|INCLUDES=0| /NOSYSTRAY /HIDE

VBSTART

Dim IE

Sub CreateIE(IE_win_position_X,IE_win_position_Y)
  Set IE = CreateObject("InternetExplorer.Application")
  IE.visible = 0

  'Window size and position
  'IE.Left = 217
  IE.Left = IE_win_position_X
  'IE.Top = 0
  IE.Top = IE_win_position_Y
  IE.Height = 652
  IE.Width = 722

  'Comment out the line to leave enabled or set to 0 to Disable
  'IE.MenuBar = 0
  'IE.ToolBar = 0
  IE.AddressBar = 0
  'IE.StatusBar = 0
  'IE.Resizable = 0
End Sub

Sub Navigate(URL)
  IE.navigate URL
End Sub

Sub WaitBusy
  do while IE.Busy
  loop
End Sub

Sub DestroyIE
   IE.Quit
   Set IE = Nothing
End Sub

Sub MakeVisible
  IE.visible = 1
End Sub

VBEND

Dialog>Dialog1
object Dialog1: TForm
  Left = 251
  Top = 97
  HelpContext = 5000
  BorderIcons = [biSystemMenu]
  Caption = 'Main Window'
  ClientHeight = 223
  ClientWidth = 439
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = True
  Position = poScreenCenter
  ShowHint = True
  OnTaskBar = False
  PixelsPerInch = 96
  TextHeight = 13
end
EndDialog>Dialog1

Let>APP_TITLE=MyApp

//initialize X and Y base co-ords of IE windows... this is where window 1 will open
//Let>IE_win_position_base_X=217
Let>IE_win_position_base_X=0
Let>IE_win_position_base_Y=0
//each subsequent IE CLR window will be offset by this ammount
Let>IE_win_position_offset=22
//This is the current positional "slot" that the IE CLR will position at.
//Valid values start at 1 and goes up to IE_win_position_max.
//We initialize at -1 because we'll increment before opening the window
//and we're multiplying the number by the offset value... window
Let>IE_win_position_number=-1
//this is the highest number of positions we'll position at
Let>IE_win_max_window_positions=10

AddDialogHandler>Dialog1,,OnClose,DoExit

SRT>DoExit
  Exit>0
END>DoExit


AddTrayIcon>C:\MyIcon.ico,MyTrayIcon,MyApp

//Add System Tray icon Handlers
AddTrayHandler>MyTrayIcon,OnClick,Do_Show_Hide_Main_Window
AddTrayHandler>MyTrayIcon,OnDblClick,Do_Show_Hide_Main_Window

//Pressing ALT+F11 will run the "ACTION" Subroutine
OnEvent>KEY_DOWN,VK122,3,ACTION


SRT>ACTION

  //calculate X and Y values for current IE CLR window positional slot
  Let>IE_win_position_number=IE_win_position_number+1
  If>IE_win_position_number=IE_win_max_window_positions
    //reset if we're at the max, 0 is first slot
    Let>IE_win_position_number=0
  EndIf
  Let>IE_win_position_X={%IE_win_position_base_X%+(%IE_win_position_number%*%IE_win_position_offset%)}
  Let>IE_win_position_Y={%IE_win_position_base_Y%+(%IE_win_position_number%*%IE_win_position_offset%)}

  Let>url=http://www.mjtnet.com/

  //new method below using VBScript and must supply X and Y co-ords to open at
  VBRun>CreateIE,IE_win_position_X,IE_win_position_Y
  VBRun>Navigate,%url%
  VBRun>MakeVisible
  VBRun>WaitBusy

END>ACTION


SRT>Do_Show_Hide_Main_Window

  //if Main Window is visible, set var main_window_visible = True
  GetDialogProperty>Dialog1,,Visible,main_window_visible
  If>main_window_visible=True
    SetDialogProperty>Dialog1,,Visible,False
  EndIf
  If>main_window_visible=True,bypass_and_return

  //if we make it here, Main Window was not visible... so make it visible

  //...for some reason, I have to setfocus on a different window first...
  SetFocus>Program Manager

  SetDialogProperty>Dialog1,,Visible,True
  //...and then I can setfocus on the Main Window
  Wait>0.2
  SetFocus>Main Window

  Label>bypass_and_return

END>Do_Show_Hide_Main_Window


Show>Dialog1

//make these bigger
Let>MSG_HEIGHT=230
Let>MSG_WIDTH=800

MDL>When you click OK to dismiss this message, the next line in the script is Wait>30 so the main script will have to wait 30 seconds.%CRLF%%CRLF%Prediction 1: the ALT+F11 hotkey will not work during this 30 seconds because the Event Handler for the Hot Key was setup by the OnEvent> command%CRLF%%CRLF%Prediction 2: In stark contrast, clicking the systray icon will work, firing "instantly" anytime during this 30 second Wait or indeed, each and every time you click it. I believe its event handler must have its own separate thread.%CRLF%%CRLF%Please try both for yourself and let me know what you find...

Wait>30

MDL>30 seconds are up, my you are patient. When you click OK to dismiss this message, you can try to recreate the Event Handler firing during VBScript collision scenario and resulting Error. You must be very fast... hit the Hot Key ALT+F11 and then IMMEDIATELY click the systray icon and if you are fast enough, you will get the error... good luck


//app spends most of its time in this loop... waiting for something to happen
Label>Loop
Wait>0.01
Goto>Loop
The fact that the Hot Key won't fire while the main script is sitting at a Wait>30 won't surprise you... that's standard behavior for events setup with the OnEvent> command.

The fact that clicking the systray icon DOES fire its event handler while the main script is sitting at a Wait>30 may surprise you... this is the power of the new v12 systray event handler... and again I say it must have its own thread.

What I find surprising though, is how the new v12 Dialog event handler behaves. The following lines setup the new v12 style Dialog event handler and there is the subroutine that will be executed... basically it ends the script.
AddDialogHandler>Dialog1,,OnClose,DoExit

SRT>DoExit
Exit>0
END>DoExit
But while clicking the systray icon fires its event handler "instantly" every time... clicking the X on the main window (Dialog1) does NOT fire its new v12 style event handler instantly every time... it actually depends on what the main script is doing... just like with OnEvent>.

To see this, while you are at the Wait>30 try clicking the X on the main window (Dialog1). I expected the whole script to close immediately... because this is a new v12 Dialog event handler which is supposed to fire "instantly" as documented in theHelp File.

Nope, the script does not close immediately, the script remains active until the Wait>30 command has waited a full 30 seconds... and then... boom, it seems to notice that you had clicked the X on Dialog1, the exit event handler seems to run and... it exits. It's almost like it "queued up" the event handler request and patiently waited for the main script to finish the line it was currently processing... the Wait>30 line.

So here, we see that the new v12 style Dialog event handler actually behaves just like OnEvent> does... it can only actually fire if main script execution is moving from line to line...

...and in contrast, the systray event handler seems more powerful in that it does not care at all what the main script is doing, it can be stuck at a Wait>30 going nowhere... and it still fires and acts instantly.

Interesting... don't you think?
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 - :-)

User avatar
Marcus Tettmar
Site Admin
Posts: 7156
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Thu Feb 03, 2011 7:36 pm

1. OnEvents are not using threads. Not yet. They *may* do in the future *optionally*. No way will they by default *if* we ever provide the options as that could actually be undesirable for many purposes, change current behaviour and confuse most people. Macro Scheduler is meant to be simple. We don't want to force users to have to read up on concurrent programming techniques. But it has always been an intention to look at ways to make them fire faster. Technically this is not trivial. It's something we intend to look at for a future version.

2. In your script the dialog close event DOES fire immediately. You can see that with the debugger or by placing a MessageModal at the top of the subroutine. However, bear in mind that just because something is running in a thread does not necessarily mean in itself that it will always fire regardless of what else is happening. If the main thread is running a tight loop and does not yield/allow the process to process messages then another thread may not fire immediately. Plus even if it does fire it's performance will clearly depend on what else is going on elsewhere. As an analogy imagine a process that hogs the CPU and therefore slows down other processes. Don't assume that just because something is an event that the usual rules don't apply. Also a dialog closing is not the same as a tray icon event firing. The former probably has more work to do - as the dialog also has to close. But again that will depend what the tray handler has to do.

3. I've already said I will look into why the VBScript issue occurs. And if it's something we can fix, then we will.

No need to reply. This thread is closed.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1086
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Tue Aug 09, 2011 3:07 pm

Hi Marcus,

Thanks for fixing this issue in release 12.1.10... very much appreciated.

This is the kind of support that keeps me excited about Macro Scheduler and future enhancements.

All the best and take care
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 - :-)

Post Reply
Sign up to our newsletter for free automation tips, tricks & discounts