May 9, 2013

Video: Screen Capture and Email Script

Filed under: Automation,Scripting — Marcus Tettmar @ 1:01 pm

Dorian has just uploaded a video demonstrating his Screen Capture and Email script. Nice video, check it out:

April 17, 2013

Paste Into Object Without Using Keystrokes

Filed under: Automation,Scripting — Marcus Tettmar @ 11:03 am

Someone asked today how it might be possible to paste what is in the clipboard into an object using Macro Scheduler without having to use keystrokes.

It can be done by sending the WM_PASTE message using the SendMessage API function.

Here’s an example:

//Sending WM_PASTE to an object causes a clipboard paste, like sending CTRL-V

//constants - here we define the WM_PASTE constant
Let>WM_PASTE=770

//we need the handle of the object we want to send WM_PASTE to - 
// - as an example let's find the handle of Notepad's edit window
// - for this example make sure Notepad is running with empty document
// - so that the window title us "Untitled - Notepad".  Modify if needed

GetWindowHandle>Untitled - Notepad,hWndParent
FindObject>hWndParent,Edit,,1,hWnd,X1,Y1,X2,Y2,result

//now send WM_PASTE to it using SendMessage API
LibFunc>User32,SendMessageA,result,hWnd,WM_PASTE,0,0

The only benefit I can see with this is that it doesn’t require keyboard focus. In theory neither should ObjectSendKeys and a CTRL-V require keyboard focus. The latter is simpler so I’d tend towards using that. And there may be some applications that work at a higher level and actually expect to see CTRL-V or similar.

Never-the-less it’s a nice example of sending a Windows message and it may be useful for some. So here it is.

March 27, 2013

Getting Data From Excel Without Office Installed

Filed under: Automation,Scripting — Marcus Tettmar @ 11:00 am

In this post from 2008 I demonstrated how to get data from Excel worksheets using Macro Scheduler’s database functions.

This works fine if Office is already installed on the PC.   But what if you want to get data from an Excel sheet and the PC you are running on doesn’t have Office installed?

Well you need the Office Data Connectivity Components which you can download from microsoft.com here:

http://www.microsoft.com/en-us/download/details.aspx?id=23734

This will install the OLEDB/ODBC drivers which DBConnect can then use to make a connection to a workbook.  You can then use DBQuery to retrieve data from a sheet as shown previously.

January 24, 2013

How to tell if the current session is a Remote Desktop session

Filed under: Automation,Scripting — Marcus Tettmar @ 10:51 am

Here’s a small piece of code which will tell you whether the current session is a Remote Desktop/Terminal Services session or not:

Let>SM_REMOTESESSION=4096
LibFunc>User32,GetSystemMetrics,isRemote,SM_REMOTESESSION
If>isRemote>0
    MessageModal>Current Session is RDP/Terminal Services Session
Else
    MessageModal>Current Session is Local Session
Endif

December 7, 2012

Custom Event Triggers

Filed under: Automation,Scripting — Marcus Tettmar @ 10:11 am

Did you know you can make just about any kind of schedule or trigger using Custom Event Triggers?

You’ll find the custom trigger option under Macro Properties in the Trigger tab.

Parsnipnose3000 has just posted a tip on Custom Event Triggers to the forums, showing how you can have a macro fire based on an image appearing on the screen. Check it out.

October 29, 2012

My Most Used RegEx

Filed under: Automation,Scripting — Marcus Tettmar @ 10:33 am

It occurred to me the other day while working on a script for a customer that I use this regular expression frequently:

(?<=TOKEN1).*?(?=TOKEN2)

It is very useful when parsing information out of web pages, or when finding elements in web pages.

What it does is pull out all the text between TOKEN1 and TOKEN2. Those could be other pieces of text, or html characters, or whatever.

As an example, recently I wrote a script which loops through all rows in an HTML table, and pulls out an order number, then looks this order number up in an Excel sheet. The order number appeared in a table cell along with other information. It was the first item inside an <i> (italics) tag and was followed by a space and then a hyphen. So I used this to pull it out of the row:

RegEx>(?<=<i>).*?(?= -),this_row,0,matches,nm,0

See how it looks for everything between the ‘<i>’ and ‘ -‘ (space then hyphen).

The next thing my code needed to do was find the ID of the single input field in the same row. This input was used to enter the order quantity, obtained from the Excel sheet. The ID is not something we know up front but it’s the only input field in the row. So I did this:

RegEx>(?<=id=").*?(?="),theInput,0,matches,nm,0

In other words, pull the text between id=” and “, which gives us the input’s ID value. We can then use that later to identify and fill the input field.

Regular Expressions are daunting at first. But eventually you find a small number of patterns help in many situations. This is one that I often find useful.

What’s your oft-used regular expression?

October 3, 2012

Sending/Retrieving Emails via Gmail

Filed under: Automation,Scripting — Marcus Tettmar @ 9:36 pm

Since version 13.2 Macro Scheduler‘s email functions now support SSL. Google’s Gmail and many other email services now insist on SSL secured connections.

To use SSL you first need to install the OpenSSL library files.

Here’s an example of sending an email via Gmail:

Let>SMTP_AUTH=1
Let>[email protected]
Let>SMTP_PASSWORD=your_password
Let>SMTP_PORT=465
Let>SMTP_SSL=1
SMTPSendMail>[email protected],smtp.gmail.com,[email protected],your name,test,hello world,

And to retrieve emails from Gmail via POP3 (make sure you have enabled this in your gmail settings):

Let>POP3_PORT=995
Let>POP3_SSL=1
RetrievePOP3>pop.gmail.com,[email protected],your_password,c:\emails\in\

September 4, 2012

Custom Dialogs: How to make a keypress alter a button click outcome

Filed under: Scripting — Marcus Tettmar @ 2:35 pm

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.

July 26, 2012

Retrieving all Items and Indexes from a Listbox

Filed under: Announcements,Scripting — Marcus Tettmar @ 11:26 am

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.

June 25, 2012

Sorting a String

Filed under: Scripting — Marcus Tettmar @ 1:22 pm

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.

« Newer PostsOlder Posts »