www.MacroToolworks.com

How To Write Reliable Macros?

 

How To Write Reliable Macros

It often happens that a macro (macro that sends keystrokes or uses mouse events) user manually creates or records works fine at the development time but starts being unreliable later (after user reboots computer, installs new software etc.).  This is not a problem of the macro program but it is natural problem of Windows events timing.  One simple example:
 Let's say user wants to create macro that will do this:  Start Notepad and type "Hello" in it.  This is quite simple and user quickly creates this macro:

<lwinkey>r<lwinkey>notepad.exe<enter>Hello

The macro will do this: opens Run dialog box (<lwinkey>r<lwinkey>), types "Notepad.exe" in it, hits Enter key to run Notepad and types "Hello" in it.  In 90% cases, It will work OK.  But what if: (i) computer is busy and Run dialog appears many seconds after all the keystrokes (Notepad.exe Hello) are already sent out, (ii) a newly installed software user re-defines LWinKey+R hot key and Run dialog doesn't appear at all.  In such cases the macro fails doing what's expected without any notice to the user.  The macro language has commands that make it possible to write the same macro safe way:

<lwinkey>r<lwinkey><cmds> <#> Open Run dialog

 <waitfor>("WIN","ACT","Run",5,0) <#> Wait for the dialog to become active
 <if_str>("_vErr==NO")
    <keys>notepad.exe<newline><cmds> <#> No (timeout) error? Let the dialog to start Notepad then...
 <else>
    <msg>(-100,-100,"%_vQuoteChar%Run%_vQuoteChar% dialog faild to open.","Message",1)
    <exitmacro>
 <endif>

 <waitfor>("WIN","ACT","Notepad",5,0) <#> Wait for Notepad to become active
 <if_str>("_vErr==NO")
    <keys>Hello<cmds> <#> No (timeout) error? Send keystrokes to Notepad then...
 <else>
    <msg>(-100,-100,"%_vQuoteChar%Notepad%_vQuoteChar% not activated.","Message",1)
    <exitmacro>
 <endif>

 This code is much longer compare to the original macro, right.  But the macro execution result is always deterministic:  Macro either executes OK or any failure is properly handled.  This becomes important especially for more complex macros that many users use.

There are a few advises that should help you to write macros that are more reliable:

1.  Some time an application the macro runs in is too slow to process all the input (keystrokes sent) in time.  In such case it can help to use <wx>(250) command that stops macro execution for 250ms and gives the application time to process previous input before the macro continues.

2.  If you write a macro that starts an application and then sends keystrokes into it, it is necessary to wait until the application loads.  You can use <waitfor> command right after the command you use to start the application.  The <waitfor> command waits until specified window appears on the screen or until it times out (timeout sets _vErr system variable and thus can be handled in the macro code).

3.  If you write a macro that copies some selected data (text, bitmap, etc.) using clipboard, it is recommended to use <clp_copyselected> command (this command waits until data are really copied to clipboard before macro execution continues) or use <waitfor> command to wait until the data are actually saved in the clipboard.

4. Replace all keystrokes and mouse actions by other commands if possible.  This means that if something can be done using a macro language command instead of using keyboard or mouse then always use the command.  For example, people often tend to open applications by simulating clicks on desktop or Start menu.  This has many drawbacks and it is always better to use <execappex> command. We can simplify and make our sample above more robust using this command:

<cmds>
 <execappex>("Notepad.exe","","",0,0)
 <waitfor>("WIN","ACT","Notepad",5,0)
 <if_str>("_vErr==NO")
    <keys>Hello<cmds>
 <else>
    <msg>(-100,-100,"%_vQuoteChar%Notepad%_vQuoteChar% not activated.","Message",1)
    <exitmacro>
 <endif>