The Macro Scheduler Water Cooler
We now have our very own Water Cooler over in the forums. Come and say hello.
Macro Recording and Automating Windows with Macro Scheduler – Tips & News
We now have our very own Water Cooler over in the forums. Come and say hello.
Macro Scheduler 13.2 Update is now available with the following changes:
Today I was asked how the outcome of a button click on a custom dialog could be altered if the ALT or CTRL key was pressed down at the time of the click.
This is possible by trapping the dialog’s OnKeyDown and OnKeyUp handlers. Using these we can detect if ALT or CTRL is pressed/released and set a flag accordingly. Then in the button’s OnClick handler we can check the value of this flag and decide what we should do.
Here’s some example code. Run it and click the button without holding down any keys. You’ll see a message saying that ALT was not pressed. Now click the button while holding down the ALT key and you’ll see the “you clicked the button while ALT was pressed” message.
Dialog>Dialog1
object Dialog1: TForm
Left = 467
Top = 241
HelpContext = 5000
BorderIcons = [biSystemMenu]
Caption = 'CustomDialog'
ClientHeight = 212
ClientWidth = 431
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
KeyPreview = True
OldCreateOrder = True
ShowHint = True
OnTaskBar = False
PixelsPerInch = 96
TextHeight = 13
object MSButton1: tMSButton
Left = 147
Top = 47
Width = 75
Height = 25
Caption = 'MSButton1'
TabOrder = 0
DoBrowse = False
BrowseStyle = fbOpen
end
end
EndDialog>Dialog1
AddDialogHandler>Dialog1,MSButton1,OnClick,doClick
AddDialogHandler>Dialog1,,OnKeyDown,doKeyDown
AddDialogHandler>Dialog1,,OnKeyUp,doKeyUp
Let>CTRL_DOWN=FALSE
Let>ALT_DOWN=FALSE
Show>Dialog1,r
SRT>doClick
//button was clicked, which key is down
If>ALT_DOWN=TRUE
MessageModal>You clicked the button while ALT was pressed
Else
MessageModal>You clicked the button without pressing ALT
Endif
END>doClick
SRT>doKeyDown
//is CTRL key pressed
If>DoKeyDown_Key=17
Let>CTRL_DOWN=TRUE
Endif
//is ALT key pressed
If>DoKeyDown_Key=18
Let>ALT_DOWN=TRUE
Endif
END>doKeyDown
SRT>doKeyUp
//was ctrl released
If>doKeyUp_Key=17
Let>CTRL_DOWN=FALSE
Endif
//was ALT released
If>doKeyUp_Key=18
Let>ALT_DOWN=FALSE
Endif
END>doKeyUp
You might be wondering how I know that the CTRL key is number 17 and the ALT key is 18. To find out the value of a key press the simplest way is just to pop a breakpoint at the start of the doKeyDown subroutine, then run the script in the debugger, press a key and look in the watch list to see what value is produced. Alternatively there’s a table here. Note that ALT is known as VK_MENU and CTRL is VK_CONTROL.
Some people have reported issue with the GetListItem command failing to work with some applications. While we investigate the issues we’ve created a small workaround. This is a .Net tool called ListInspector. It’s a command line tool which you can pass a listbox handle to and it will dump out a list of all the items and their indexes.
Here’s an example of use:
//get handle of putty and find handle of listbox GetWindowHandle>PuTTY Configuration,pHwnd FindObject>pHWnd,ListBox,,1,hWnd,L,T,R,B,res //run ListInspector to get a list of items Let>RP_WINDOWMODE=0 Let>RP_WAIT=1 Run>cmd.exe /C "%SCRIPT_DIR%\ListInspector.exe" %hWnd% > %TEMP_DIR%\items.txt ReadFile>%TEMP_DIR%\items.txt,items //find the index of the item we want Let>item_required=Pluto Server RegEx>\d*(?=:%item_required%),items,0,matches,nm,0 If>nm>0 Let>index=matches_1 MessageModal>Index of %item_required% is %index% Endif
The script here gets the items of the session selection box in the Putty SSH client. The first thing it does is get Putty’s window handle, then find the handle of the list box we want to inspect. It then runs ListInspector.exe and passes the listbox handle to it, piping the results to a temporary file. It then reads in the file and uses a RegEx to extract the index for the item we are looking for.
This is useful for those listboxes which don’t allow us to “drill down” properly and where the items and order of items may be dynamic, leaving us with no easy way to automate the selection of an item. Using ListInspector we can get the item’s index and then we know how many times we need to “Press Down” (first using Home to make sure we’re at the top).
You can download ListInspector here. The zip file contains the example script and a small readme file. .Net 2.5 or higher is required.
In the forums this morning PepsiHog asked for some code to sort a string of numbers.
We have a built-in method for sorting arrays. But here we want to sort a string of characters. E.g. we want the string “4731” to end up as “1347”.
I ended up writing a reusable subroutine which will sort any length string alphanumerically. I thought I’d post it here as it demonstrates a few useful ideas:
//CharSort, parm1: the string to sort, parm2: name of variable to return
SRT>CharSort
Let>LOCALVARS=1
Let>tmp=
RegEx>.,CharSort_Var_1,0,matches,nm,0
ArraySort>matches
Let>x=0
Repeat>x
Let>x=x+1
Let>this_char=matches_%x%
Let>tmp=%tmp%%this_char%
Until>x=nm
Let>LOCALVARS=0
Let>%CharSort_Var_2%=tmp
END>CharSort
To use the subroutine do something like:
Let>MyString=317536492750930
GoSub>CharSort,MyString,{"MyString"}
MessageModal>MyString
This demonstrates a number of things:
– How we can call a subroutine with parameters, and how we can use one of those parameters to set a “result” variable (note the second parameter is set to a string value, and the subroutine sets a variable with this name to the result).
– How we use LOCALVARS to ensure the subroutine has local scope (except when we need to set the return variable). This is important for functions we might re-use elsewhere and drop into other scripts, as we would want to avoid the subroutine modifying any existing script variables. By using local scope we make sure the variables used in the subroutine are local only to that subroutine.
The subroutine works first by splitting the string into an array of characters. It does this by using a Regular Expression which identifies all characters (“.”). RegEx returns an array of matches, which will therefore be all the characters in the string (because “.” means match any character). We can then sort this array using ArraySort and then finally loop through the array and concatenate each item back into a string.
Despite our FAQs we get asked a version of the following question at least once a week:
“I just wrote my first macro with Macro Scheduler and it works great but if I lock Windows it stops working, is this a limitation of the trial version”.
My most recent answer to this was as follows:
No, it’s a limitation of how Windows works. I assume that your script needs to simulate a user (i.e. send keystrokes and/or mouse events and needs to “see” windows).
When Windows is locked or logged out *windows cease to exist* and *there is no input console*. Ergo you cannot simulate a user when Windows is locked or logged out. There is nothing anyone can do about this as that is simply the way Windows works.
A more detailed and technical explanation of this can be found here:
http://www.mjtnet.com/msfaq171.htm
http://www.mjtnet.com/msfaq17.htm
Think about it for a second – can YOU use Windows when it is locked or logged out? Of course not. But most people don’t realise that when you lock or log out of Windows the user’s “window station” literally no longer exists, and applications no longer have UIs. While a process may exist, it has no windows and UI objects simply aren’t there. So there’s nothing to interact with. Furthermore the only thing that has keyboard/mouse focus is the security console. So you cannot send mouse/keyboard events.
So in short you cannot automate user interfaces when Windows is locked or logged out.
Command line tasks, and tasks that do not need to access a user interface (interact with windows) may still be possible assuming they do not require logged on credentials.
The only solutions are:
1. Leave Windows logged in
2. If you are running Vista/Windows7/2008 Server you can use Macro Scheduler’s AutoLogon system. See under Macro Properties. This will log Windows back in on schedule, run the macro, and then log out again.
We have a growing list of freelance script developers which we draw from whenever we receive a request for local assistance. If you are a freelance script developer and would like to be considered for potential projects please drop me a line with your details and a summary of your experience so that we can add you to the list.
I recently wrote a small macro for a customer which does an HTTPRequest via SSL. This requires that OpenSSL is installed. But the customer wanted to know if there was any way of distributing the macro to his users without having to install OpenSSL on all their PCs.
Thanks to our wonderful forums one of our users has already figured out how to do this and it turns out only 2 DLLs are required and can be placed in either the Macro Scheduler program folder, or, in the case of a compiled macro, the exe’s folder.
Adroege says:
I use this solution:
Download the “binaries” from this page as a zip file
http://gnuwin32.sourceforge.net/packages/openssl.htmUnzip the contents
find the files libeay32.dll (version 0.9.8.8) and libssl32.dll
(version 0.9.8.8) in the Bin folderMake a copy of libssl32.dll and call it “ssleay32.dll”
Now just deliver all 3 DLL files in the same folder as the
compiled Macro Scheduler EXE
(libeay32.dll libssl32.dll ssleay32.dll)Using this method, I didn’t have to do any special SSL “install”,
run regsvr32.exe, or do any registry hacks. It just works.
And rullbandspelare responds:
It appears to work with just putting
ssleay32.dll and libeay32.dll in the same folder.
Even I learn stuff from our forums, or at least find answers more quickly. A great resource. Thanks guys.
Macro Scheduler 13.1.06 maintenance release is now available.
Macro Scheduler 13.1.05 maintenance release is now available.