November 18, 2007

Application and System Monitoring

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

A short roundup of resources and ideas for using Macro Scheduler for system and software monitoring.

Event Log Monitoring

Here’s a tip showing how to create a script to monitor event log messages:
http://www.mjtnet.com/usergroup/viewtopic.php?t=4256

Process/Service Monitoring

This script demonstrates a function called IsProcessRunning to check if a specific process is running. Use it to create a monitor to watch a specific application process and make sure it is running. It could send an email if the process is no longer running. The same script shows some code to get the status of a service which could be used to create a service monitor.

Monitoring Files

Macro Scheduler has built in functions to see if a file exists, get file lists, get file dates, see if a file has changed, read from text files, read from INI files and more. See the IfFileExists, ReadFile, ReadLn, GetFileList, FileDate and ReadIniFile commands in the help file.

Monitoring Web/Intranet Resources

Use HTTPRequest to retrieve data from web resources, or FTPGetFile to download a file from an FTP server. Monitor email with ReceivePOP3.

Monitoring Windows and User Interfaces

If you just want to check that a window exists use IfWindowOpen. GetActiveWindow will return the active window title. Maybe you need an alert when a window contains a specific message, or piece of text. GetWindowText will retrieve all detectable text in a Window. Use GetControlText to retrieve text from a given control class and instance.

But what if you need to monitor a graphical element, or look for some non-detectable text? Use FindImagePos. The Image Recognition functions mean any kind of user interface can be monitored and/or controlled. You can also monitor applications running remotely (e.g. in Windows Terminal Server or Citrix sessions, or even non-Windows VNC apps) or in virtual environments.

One of our customers provides hosted software solutions to clients who require a high degree of up-time. Their clients’ businesses depend on their software remaining online. So they have used AppNavigator to create UI monitors that watch their applications and alert them if an interface goes down.

Alerts

The Event Log monitor example above uses email to alert the system administrator when an event is detected. Email is probably the most common method. Email can also often be used to send an SMS message (check with your mobile carrier). But an alert could just be a message box popup, or the script could run another application, write to a file or database or call a web resource. Pretty much any kind of alert could be created.

Have you used Macro Scheduler for system monitoring? If you have an example or story to share, please post a comment.

October 8, 2007

Screen OCR to Retrieve Otherwise Undetectable Text

Filed under: Automation,Scripting — Marcus Tettmar @ 7:56 am

Some while ago I wrote this post about how to script a tool called Textract to perform OCR against the screen. Well gpulawski has just posted this tip in the forums pointing out that Microsoft Office 2003/2007 comes with something called MODI (Microsoft Office Document Imaging) which can OCR a bitmap or TIFF file and is scriptable. Very cool.

We can use MODI transparently in a Macro Scheduler script to use OCR to extract text from a Window. I’ve posted an example here.

This is really useful if you have a window that doesn’t expose text as text objects and you can’t get at the text any other way (e.g. via the clipboard or controls). You may want to check for the existence of a certain string in a window, or wait for a particular word or phrase to appear in order to determine when a process has completed. If the control doesn’t expose the text and the text cannot be copied to the clipboard, OCR may be the solution.

September 18, 2007

WebRecorder Update

Filed under: Announcements,Automation — Marcus Tettmar @ 8:51 am

Today we have released an update to WebRecorder:

WebRecorder GUI: 1.73
IEAuto.DLL: 1.79

Fixed: ContainsText unable to access content of some frames
Fixed: ExtractTag unable to access content of some frames

This update also correctly reports the version number of the WebRecorder GUI and the IEAuto.DLL version number. It now therefore works better with the online update checker and should be less confusing when checking for updates! 🙂

WebRecorder Info | Evaluation Downloads | Registered Updates

August 7, 2007

Keep it Simple – Shortcuts and Applications

Filed under: Automation,Scripting — Marcus Tettmar @ 7:47 am

We had a customer email us the other day having a problem getting his macro to work reliably. He wanted to start an application, so he had written a macro to left click on the application’s shortcut on the desktop. But sometimes the icon moved. He wanted to know how to reliably know where the icon was.

Reality check. There’s an easier way! You don’t need to know where the icon is.

Let’s just think about this for a second. What is a shortcut? As its name suggests it’s a shortcut to something. In this case the shortcut was to an application. We need to start the application. So why not start it directly? Why click on the shortcut at all?

Right clicking on the shortcut and selecting properties tells us the path of the application in the “Target” field. Usually all we need to do is copy that and stick it in a Run Program command:

Run Program>C:\Program Files\FileZilla\FileZilla.exe

Occasionally an application needs to start in a different folder. In the shortcut properties you’ll see a field called “Start in”. If necessary copy the value there and put it in a Change Directory command. So we end up with:

Change Directory>C:\Program Files\FileZilla
Run Program>C:\Program Files\FileZilla\FileZilla.exe

You can even run a shortcut itself:

ExecuteFile>C:\Documents And Settings\Marcus\Desktop\FileZilla.lnk

This way the shortcut is executed just as if you clicked it and all the attributes of the shortcut are used.

No mouse clicks needed!

If you really *do* want to find an icon on the desktop reliably, use Image Recognition.

Or you can even use keystrokes to invoke a shortcut.

SetFocus>Program Manager
Send>FileZilla
Press Enter

But for just starting an application, all this is rather unnecessary. Run the application directly.

July 2, 2007

Methods for Accessing Excel Data

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

UPDATE: 25/09/2012 – This article was written in 2007 before Macro Scheduler contained native Excel functions and native database access. Furthermore, since this article was written Excel no longer supports DDE. This article has therefore been superseded and should only be used as a reference for use with older versions of Macro Scheduler and/or older versions of Excel. For the latest version (currently v13) look at the native Excel functions (XLOpen, XLGetCell, XLSetCell etc) and the native database functions. For an example of querying Excel using the native database functions see this post.

There are a number of ways that Macro Scheduler can interact with Excel to retrieve or modify data. I’ll introduce you to three methods here.

1) Forget Excel!

Yes, sometimes you can forget about Excel. Often people actually just want to read from/write to a CSV (Comma Separated Values) file. Because Excel is on so many people’s computers and is the default file association for CSV files it seems many people think CSV files are Excel files. Not so. If the file you want to read is a .CSV file then it’s really just a text file containing the data. Each line represents a row of data and each column is separated by commas (or sometimes semicolons – but it could be anything else). Open the CSV file up into Notepad and you will see something like this:

"id","description","quantity","price"
5343,"earl gray tea",32,5.64
2435,"decaffeinated coffee",26,4.67
1433,"chocolate cookies",12,3.98

String values may or may not be delimited by quote characters, as in my example above.

We can forget about Excel if we want to read this data in with Macro Scheduler. We can instead just go direct and use the ReadFile or ReadLn functions which are used to access text files. This post shows you how to read a text file in line by line. The only part missing is to extract each field or column from each line (record). Well, as with the ReadFile loop in example 2 of this post, we can use the Separate command, and specify the comma character as the delimiter:

Let>comma=,
Separate>line,comma,fields

This would give us fields_1, fields_2, fields_3 and fields_4 containing each item in the line. Combining that code into my ReadFile loop example to show each field would give:

ReadFile>c:\\\temp\\\test.txt,TheFileData
Separate>TheFileData,CRLF,Lines
Let>comma=,
Let>k=1
Repeat>k
  Let>CurrentLine=Lines_%k%
  //extract each field
  Separate>CurrentLine,comma,fields
  MessageModal>%fields_1% %fields_2% %fields_3%
                       %fields_4%
  Let>k=k+1
Until>k>Lines_Count

Want to remove the quotes from the string fields? Use StringReplace:

StringReplace>fields_2,",,fields_2

To write data out to a CSV file simply use the WriteLn command:

Let>LineToWrite=1234,cornflakes,1,1.99
WriteLn>filename.csv,result,LineToWrite

Update: Here’s another way to read CSV files which also solves the problem of quoted field values containing commas.

2) Use DDE

EDIT: DDE is no longer supported in the latest versions of Excel. See editor’s note at top.

DDE is an abbreviation for Dynamic Data Exchange and is an old protocol for interfacing with applications. It has largely been superseded by other methods such as COM but Microsoft Excel still supports it and it provides a simple way to access cells in Excel directly.

Use the DDERequest command to retrieve an item of data from Excel. Excel must be running and the spreadsheet must already be open. We could easily make our macro open the worksheet for us using the ExecuteFile command (or Run Program). We then use DDERequest something like this:

DDERequest>Excel,c:\\\documents\\\example.xls,R1C1,
      myVariable,60

The first parameter is the Server name, which is always just Excel for Microsoft Excel. The second parameter, the DDE “Topic”, should be set to the filename of the spreadsheet (which must be open). The third parameter specifies the cell to retrieve. This is constructed RnCn (Row n, Column n). Use numeric values for both Row and Column. So Cell A1 would be R1C1. Cell B1 would be R1C2. Cell D14 would be R14C4, etc. The next parameter is the variable name to store the result in. And finally we specify a timeout value in seconds. If the command fails to locate within that amount of time it will timeout and the result variable would contain “DDE_TIMEOUT”.

The second parameter can also contain a sheet name when you want to access data on a particular worksheet. The Sheet name is added after the filename, separated from the filename by a colon. So parameter two would become: Filename:Sheetname

One thing to note is that Excel often appears to append a CRLF sequence to the end of the data. Therefore we should remove it as follows:

StringReplace>myVariable,CRLF,,myVariable

Take a look at the “Extract From Excel” sample script which comes with Macro Scheduler for an example which uses the DDE method to retrieve data from Excel and paste it into Notepad.

To modify a cell value, or write a value to Excel we use the DDEPoke command as follows:

DDEPoke>Excel,c:\\\documents\\\example.xls,R2C3,
                                      56.75

Again, the spreadsheet must be open for this to work. The above puts the value 56.75 into cell C2 (row 2, column 3). As with DDERequest you can add a worksheet name in parameter two if needed (Filename:SheetName).

For another example see:
Exchange Data with Microsoft Excel The Easy Way

3) VBScript via COM

VBScript offers the most flexible and powerful method of interacting with Microsoft products. Not only can we modify data using this method we can also control almost any part of Excel. Anything that you can program or record in Excel can be converted into VBScript code and used inside a Macro Scheduler script.

Here is an example script with some functions you can use to retrieve and modify Excel cells:

//Put this VBSTART..VBEND block at top of script
//to declare the functions once
VBSTART
Dim xlApp
Dim xlBook

'Opens the Excel file in Excel
Sub OpenExcelFile(filename)
  Set xlApp = CreateObject("Excel.Application")
  xlApp.visible = true
  Set xlBook = xlApp.Workbooks.open(filename)
end sub

'Use this to close Excel later
Sub CloseExcel
   xlApp.quit
   Set xlApp = Nothing
End Sub

'Retrieves a cell value from the specified
'worksheet
Function GetCell(Sheet,Row,Column)
  Dim xlSheet
  Set xlSheet = xlBook.Worksheets(Sheet)
  GetCell = xlSheet.Cells(Row, Column).Value
End Function

'Sets specified cell of specified worksheet
Function SetCell(Sheet,Row,Column,NewValue)
  Dim xlSheet
  Set xlSheet = xlBook.Worksheets(Sheet)
  xlSheet.Cells(Row,Column).Value = NewValue
End Function
VBEND

//Do the business
VBRun>OpenExcelFile,%SCRIPT_DIR%\example.xls
VBEval>GetCell("Sheet1",5,4),theValue
MessageModal>Cell value: %thevalue%
VBEval>SetCell("Sheet1",28,2,998),nul
//VBRun>CloseExcel

This code is constructed in such a way to allow you to call the VBScript functions from regular MacroScript code and therefore retrieve the data to regular variables.

For another example see:
Automate Excel with VBScript

You can also run Excel macros:
Run Excel Macros and VBA Routines

And, as stated above, you can do a whole heap of other things. Search the forums for Excel to find other examples. Converting from Excel VBA to Macro Scheduler VBScript is a topic for another day but hopefully you can get an idea from these simple examples.

___
You may also be interested in: Accessing Databases

June 27, 2007

Office 2007 VBA Shell Bug?

Filed under: Automation,Scripting — Marcus Tettmar @ 3:12 pm

When trying to execute a third party application, such as Macro Scheduler, from VBA in Office 2007 using the Shell function the following error is returned:

“Invalid procedure call or argument”

Sometimes you might want to run a Macro Scheduler macro from Office using this method and get this error. Searching the web reveals many people reporting the same error when trying to run other applications, including other Office apps! E.g.:

Shell “c:\my macros\macroA.exe”

I suspect there’s an issue with spaces in the path but trying to embed extra quotes with chr(34) doesn’t seem to help. The Shell function also doesn’t provide a way to specify command line parameters other than including them in the entire command string.

The solution is to use the ShellExecute API function. Declare the function in the General Declarations section of your VBA module using this code:

Private Declare Function ShellExecute Lib “shell32.dll” Alias “ShellExecuteA” (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Then you can use the function as follows:

ShellExecute 0&, “”, “c:\program files\macro scheduler\msched.exe”, “calculator”, “”, 1

This code runs the Calculator sample macro in Macro Scheduler.

To run an application with no command line parameters leave the fourth parameter empty:

ShellExecute 0&, “”, “c:\my macros\mymacro.exe”, “”, “”, 1

May 18, 2007

First Winner of Scripts & Tips Competition

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

We have our first successful entry to the Scripts & Tips 10 Year Anniversary Competition. Robert White sent in this excellent Cookie Monitor script. It’s a nicely written script which is both very useful and also demonstrates effective use of a non-modal dialog and other scripting features such as looping, reading a list of files, string manipulation, and reading from the registry. The beauty of this script, as a demonstration script, is you can run it as-is and it will work on your machine without any modification. Grab the script here.

We’ve rewarded Robert with an extra year of upgrade protection. Well done Robert, and thanks for the script!

February 23, 2007

Remote Citrix Automation the Easy Way with AppNavigator

Filed under: Automation — Marcus Tettmar @ 8:36 pm

In my last post I showed you how to write an Image Recognition script in Macro Scheduler to automate a remote Citrix session. I demonstrated how to use Image Recognition functions to look for screen objects and create an Outlook email.

Well, in this demo I show you how to automate the exact same process using AppNavigator. The video is just over two minutes long and that includes the time taken to build the routine and play it back! You can see that there is no coding involved. Anyone who knows the process could create the routine.

Watch the video and compare to building the same process with code.

This is a very basic example where all we do is create an email. In the real world we’d take it further and we may also want to add failover checks to handle situations where window objects fail to appear or change. With the first solution we’d need to modify the code to handle this and our script would become much more complicated. With AppNavigator it would be a simple case of adding a not found action to the relevant images. We could tell it to try again, stop, jump to a different image, send an email (with a screen shot) to admin, run a script … etc. Maintenance becomes so much easier and less prone to introducing bugs compared to modifying long scripts of code.

February 20, 2007

How to Use Image Recognition

Filed under: Automation,Scripting — Marcus Tettmar @ 12:11 pm

What is Image Recognition?

Update. Image Recognition has been vastly improved and simplified since this article was written and in v13 we introduced an Image Recognition Code Wizard. Watch this video to see how simple it is.

Image Recognition allows Macro Scheduler to find a bitmap (needle) in another, larger, bitmap (haystack) and return its position. The larger bitmap could be a snapshot of the screen, and the smaller bitmap could be a capture of a toolbar button or some other screen object. Therefore Image Recognition allows us to locate objects on the screen, graphically. We can also wait for images to appear on the screen. So Image Recognition allows us to automate any kind of graphical interface. We can make the script wait for images to appear on the screen, find screen objects and therefore send mouse events to the correct part of the screen to focus or control the objects.

The functions most used for Image Recognition are as follows:

WaitScreenImage
FindImagePos
GetScreenRes*
ScreenCapture*

*Note: GetScreenRes and ScreenCapture are no longer required (since v9.2) as you can now specify SCREEN for the haystack in FindImagePos

Building an Image Recognition Script

In this video I demonstrate the Image Recognition functions to automate Outlook running in a remote Citrix session. Traditionally automating interfaces in remote environments is difficult without having Macro Scheduler running on the remote server. Trying to automate a remote desktop with traditional commands is unreliable since the client doesn’t know anything about the windows and objects running on the remote server – all it sees is a graphical copy of the screen. This is why image recognition is so powerful in such situations.

Watch the video and then continue reading this article to learn how the script works.

In the video I first tell Macro Scheduler to find the position of a button on the screen. I first want the macro to find this button:

New Email Button

First I use the image capture tool to capture an image of this button from the screen and save it to a .bmp file. The image capture tool is available in the editor under the Tools menu, and also from the Capture button on the Command Builder dialog for the FindImagePos and other image recognition functions. I save the image to d:\citrix-images\new2.bmp.

The first thing I need my script to do is determine the dimensions of the screen. This is so that I can capture the entire screen later in the script. So I use the GetScreenRes function:

GetScreenRes

This returns the width and height of the screen in variables sX and sY. Next we capture the current screen to d:\screen.bmp using the ScreenCapture command:

ScreenCapture

So this captures the entire screen, from 0,0 to sX,sY returned by GetScreenRes.

Note: Since version 9.2 the above two steps are no longer necessary as it is now possible to specify SCREEN in FindImagePos and do not have to first copy the screen to a bitmap

Now we want the script to look for the new email button in this screen image using the FindImagePos function. This looks like this:

FindImagePos

This looks for new2.bmp inside screen.bmp using a color tolerance of 20 (where 0 is not tolerant and the pixel colors must match exactly and 255 is highly tolerant and anything would match!). We set the fourth parameter to 1 to tell it to return the center coordinates of the image match. If this was zero it would return the top left position in screen.bmp where a match was found. But I would like to return the coordinates of the center position of a match. i.e. the center of the new email button on the screen. XPos and YPos are our variables the coordinates will be stored in. These are arrays. So the first match will be in XPos_0,YPos_0, the second match (if any) in XPos_1, YPos_1, etc. imgs is the return variable which is set to the number of matches found.

So now we can say “if a match was found, move the mouse to the first position and click”. This looks like:

MouseMove

Since we captured the entire screen, the coordinates returned by FindImagePos map directly to screen coordinates. If the ScreenCapture command had not captured the entire screen we would have to add the top x,y coordinates given in the ScreenCapture command as offsets to the MouseMove command. As we captured the entire screen x,y was 0,0 anyway. Sometimes it is not necessary to work with the entire screen and we could instead capture just a Window. Like this:

MouseMove Relative

One would then have to add X,Y to any position returned by FindImagePos in order to map to an absolute screen position.

But back to the demo. We now have code which finds the new email button on the screen and clicks on it. This causes a new window to appear. If we were automating an application running on our desktop we could simply use the good old WaitWindowOpen command which is given the window title and waits for that window to appear. But, remember, this demo is automating a remote environment. The windows are on another computer. We don’t know about window titles. Citrix just sends us an image of the screen of the remote computer. So instead we will use the WaitScreenImage function. This is nice and easy:

WaitScreenImage

I used the capture tool to capture an image of the top left part of the new window – showing the window icon and title:

Window Title

That was saved to title2.bmp. So the above function simply watches the screen and waits until it finds this image on the screen. When that happens we know the new window has appeared.

By the way, you could create your own WaitScreenImage using a loop containing ScreenCapture and FindImagePos. This would give you more control and build in a timeout if required. But WaitScreenImage is a quick and easy way to wait for an image to appear on the screen without any further coding.

Finally, now the script knows the new window is present it can send some keystrokes, so we send some text to create the email. In the real world we’d probably use more image recognition to manipulate other objects on this new window and continue using the same techniques.

send keystrokes

Tips

For performance reasons the image recognition functions do not check every single pixel in each image. That would take far too long. Instead a random sample of pixels is taken from the small “needle” image and each of these is checked against all the possible matching pixels in the larger “haystack” image. For this reason it is possible to get false positives if the image you have captured is not very specific. E.g. consider these two images:

done

connecting

These images are largely similar since we have too much gray area. If the random sample is all from the gray area both would match. These are from a status bar, and if we were searching for Done we could easily find Connecting. The solution here is to make the image smaller so that there is less of the gray background. Alternatively find something more specific on the screen.

Note: You can override this behaviour by setting the number of pixels to scan using the FIP_SCANPIXELS variable, and since v12 this can be set to ALL to perform an exhaustive match and tests reveal no noticeable performance hit in doing so.

AppNavigator Does it Without Code

AppNavigator takes all the coding away from image recognition and also adds some more power. It is clever enough to narrow down a search if it first finds too many matches, or none at all, and it also remembers the part of the screen a match was found in. Next time it will concentrate on that part of the screen and only search the entire screen if a match is not found. This increases performance and reliability. With AppNavigator you can capture screen objects and assign them actions without having to write code like that presented here. AppNavigator can be told what to do when an object can’t be found, and can also navigate the extraction of data from Excel or Access without coding that either.

To see how easy it is to create the same process with AppNavigator see my next post.

Update 12th October 2007: Macro Scheduler 9.2 (and above) now lets you specify SCREEN in the haystack parameter of FindImagePos. Therefore if you are scanning the entire screen you no longer need to use GetScreenRes and ScreenCapture to capture the screen to a bitmap file first. Just specify SCREEN in FindImagePos.

January 19, 2007

AppNavigator – Point and Click Enterprise Automation

Filed under: Announcements,Automation — Marcus Tettmar @ 3:07 pm

AppNavigator is a powerful new tool that lets you create automation routines graphically, without any need to write code. With this software you can create processes by highlighting screen objects and assigning actions to them. Any process can be automated based on simple graphics – by “seeing” the screen. Just show AppNavigator what to watch for, and what to click on, and build up a process based on visual cues. You can read more information here. We also have some Flash video demos available:

Creating an AppNavigator Process
Playing back an AppNavigator Process

« Newer PostsOlder Posts »