February 13, 2009

Image Recognition Common Mistakes

Filed under: Automation — Marcus Tettmar @ 12:16 pm

This is a copy of a reply I gave in the forums recently which I thought would be useful posted here.

It sometimes seems to surprise people that the only reason FindImagePos will fail to find an image on the screen is because …. that image is NOT on the screen! I’ve had people swear blind the image they are seeking is on the screen but when I’ve opened up the screen image and the needle image in Paint I can see big differences.

Here are some common mistakes I’ve seen that can lead to not finding the image you want Macro Scheduler to find (or rather, looking for the wrong image):

Mistake 1: Not using the built in Image Capture Tool. ALWAYS use the Macro Scheduler Image Capture tool. Other image editors may save with a different colour depth etc. To ensure like-with-like comparisons ALWAYS use the Macro Scheduler Image Capture Tool.

Mistake 2: Capturing the object when it is in a different state to how it appears at run time. E.g. buttons look different when they are focused, menus look different when they are selected, tooltips appear when the mouse is over objects, sometimes even window captions appear different when the window is not focused, sometimes objects look different when the mouse is hovered over them. Take all these things into consideration and make sure you capture the image as it will appear at the point in the process where you want to find it. You may need to use the delayed capture feature of the Image Capture Tool so that you can arrange focus before you capture the object. Consider making the script move the mouse to 0,0 in case the mouse ends up hovering over the button you’re looking for at runtime. I’ve seen buttons look different if the window is focused. If you have the window focused when you captured it you’ll need to make the script focus it before looking for it. Or vice-versa. Etc etc

Mistake 3: Capturing too much of the screen. FindImagePos compares a random sampling of pixels in the needle image and target area. So if you capture an area with lots of background it’s feasible that only the background pixels get chosen and you’ll end up with lots of matches. Be more specific in your captures, and if you need to, increase FIP_SCANPIXELS to make it scan more pixels. Update: in V12 you can set FIP_SCANPIXELS to ALL.

Mistake 3a: Thinking it didn’t find the image when in fact it DID find it, but it also found other possible matches. The function returns the number of images found and an array of matches. If you are clicking on the first match and it is not the right place, look at the number found. Consider what to do if number of matches is more than 1.

Mistake 4: Looking for the image at the wrong time – getting the order of events all wrong.

Some issues that can cause problems:

Graduated or patterned backgrounds. If you capture an object that is on a non-smooth background and have to capture some of the background as well, then if the object appears at a different position at runtime you may fail to find a match, because the background is not smooth. As with Mistake 3 above you probably just need to be more specific about what you capture. Or, if that isn’t possible, see if you can change the background. There’s no harm in making life easier for ourselves by setting the environment up to be a little more predictable so that we can automate/test more reliably. Don’t forget you can also change the colour tolerance parameter to handle small differences in colours.

Sometimes it’s helpful for diagnostic purposes to use ScreenCapture to capture the screen to a file prior to your FindImagePos call. Then, later, if it didn’t work as you expected you can open up the screen image and work out why.

See also: How to use Image Recognition.

February 12, 2009

Macro Scheduler 11.1.04 Update

Filed under: Announcements — Marcus Tettmar @ 3:27 pm

Macro Scheduler 11.1.04 Update is now available with the following fixes:

  • Fixed: Autologon failing to save password correctly
  • Fixed: Backup on Save not working for standalone editor
  • Fixed: Editor status bar not always reflecting modified status
  • Fixed: Improvements to dialog block updating from “Update Dialog” menu
  • Fixed: Debugger: Breakpoint after an Include not showing Include lines/line number confusion
  • Fixed: Step Over confused by GoSub inside a subroutine
  • Change: Debugger no longer temporarily disables wordwrap – no longer required
  • Change: Editor line numbers now show at top of wrapped lines
  • Added: Clicking in editor margin selects entire line

Registered Downloads/Upgrades | Evaluation Downloads | New License Sales

February 5, 2009

Twitter – What, Why, How?

Filed under: General, Web/Tech — Marcus Tettmar @ 2:20 pm

If you’re one of those who has heard of Twitter but just doesn’t quite “get it” yet you should find Scott Hanselman’s How To Twitter – First Steps and a Twitter Glossary useful. It explains what Twitter is, why it’s useful and how to tweet.

I didn’t get it at first. I wasn’t quite sure what I would get out of it. Most people who now use Twitter regularly were probably the same to begin with. Now I realise how useful it is. I follow friends, people and companies that I find interesting and I want to stay up to date with. I follow news sites like the BBC and CNN. I probably get most of my news via Twitter now (In our house the TV seems to be permanently tuned to Nick Jr these days!). Most of the bloggers I read now tweet their blog updates, so I no longer need to monitor their RSS feeds.

It’s useful. It’s fun too. Even if you don’t have anything to say, you can get a lot out of following people that interest you. And, as Scott says, the nice thing is if you want to respond you can just jump in and reply to anyone.

So if you’ve been wondering what all the fuss is about, read Scott’s blog post, jump in and join the conversation. You can start by following me. My twitter ID is http://twitter.com/marcustettmar 🙂

Generating Random Characters and Strings

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

Macro Scheduler has a Random function which will give you a random number between a specified range. Every now and then I am asked how you can create a random character or random character string.

The solution is to use VBScript’s Chr function which returns the character for the specified Ascii code. So we can use Random to get a random number within the required Ascii range, and then use Chr to get the corresponding character. There are a few examples in the forums, such as this one.

I was recently asked how to generate a random character from A to Z. Here’s my response:

Look at the ASCII table: http://www.asciitable.com/

Let’s look at upper case only first:

A is ascii code decimal 65
Z is ascii code decimal 90

So if we want a random character from A-Z inclusive we want to get a random number in that range (65 to 90).

Clearly it’s a range of 26. Random gives a value from 0 to range-1. So:

Random>26,random_number

So to get that into our range we clearly need to add it to 65, because the ascii range begins at 65 for “A”:

Let>ascii_code=65+random_number

Now we have an ascii code in the required range. So now use VBScript’s Chr function which returns the corresponding character for the ascii code:

VBEval>chr(%ascii_code%),random_char

So, in long form:

Random>26,random_number
Let>ascii_code=65+random_number
VBEval>chr(%ascii_code%),random_char

Or, shorter version:

Random>26,random_number
VBEval>chr(%random_number%+65),random_char

That will give you a random character between A and Z inclusive.

If you want lower case then the range is 97 – 122. There are some characters in between. So if you want to mix lower case and upper case, you could either look at the entire range, discarding any results that appear between the two, or throw a coin (Random>2) to determine whether to do the upper case range or the lower case range, or, I think simpler, randomly convert to lower case, e.g.:

Random>26,random_number
VBEval>chr(%random_number%+65),random_char

Random>2,UpperOrLower
If>UpperOrLower=0
  VBEval>LCase("%random_char%"),random_char
Endif

MessageModal>random_char

Remember, to use VBScript you need a VBSTART/VBEND block in your script, even if it is empty. Stick it at the top. So the whole example script becomes:

VBSTART
VBEND

Random>26,random_number
VBEval>chr(%random_number%+65),random_char

Random>2,UpperOrLower
If>UpperOrLower=0
  VBEval>LCase("%random_char%"),random_char
Endif

MessageModal>random_char

February 2, 2009

T-Shirt Winners for January 2009

Filed under: Announcements — Marcus Tettmar @ 11:02 am

Well I only announced the new forum reputation system on the 21st Jan, but I did say that awards will be made based on the previous month. So it was a short month last month. The top three reputation point winners, and the points awarded were as follows:

mtettmar: 21
Me_again: 13
Bob Hansen: 10

Now, clearly I’m excluding myself from this promo (I already have a T-shirt anyway) so T-shirts (or mug, or mousemat) go to Me_again and Bob Hansen. Congratulations, and thanks for your contributions.

Winners: please PM/email me with your requirements/preferred size and mailing address.

January 30, 2009

Macro Scheduler 11.1.03 Update

Filed under: Announcements — Marcus Tettmar @ 10:45 am

Macro Scheduler 11.1.03 Update is now available with the following fixes:

– Compiled exes with NOSTOPKEY set will show APP_TITLE in tray icon hint
– Fixed: Editor code folding/autoinsertion confused by nested subroutines
– Fixed: Step Over (Shift-F8) not working

Registered Downloads/Upgrades | Evaluation Downloads | New License Sales

My apologies for another update so soon after the last. Thanks to Keith for reporting the issue with nested subroutines confusing the editor’s syntax highlighter, and to Tim for spotting that Step Over wasn’t working. These issues probably don’t effect 99.9% of people, but for Keith and Tim they were a big pain. It was tempting to just provide the fix to them rather than interrupt everyone with yet another update announcement. But there could be others out there with the same issues and I’d rather everyone benefited. So here it is.

January 29, 2009

We Eat Our Own Dogfood

Filed under: General — Marcus Tettmar @ 3:54 pm

I just read this post on the Coding Horror blog and it struck a chord:

In software circles, dogfooding refers to the practice of using your own products. It was apparently popularized by Microsoft:

The idea originated in television commercials for Alpo brand dog food; actor Lorne Greene would tout the benefits of the dog food, and then would say it’s so good that he feeds it to his own dogs. In 1988, Microsoft manager Paul Maritz sent Brian Valentine, test manager for Microsoft LAN Manager, an email titled “Eating our own Dogfood” challenging him to increase internal usage of the product. 

We certainly eat our own dogfood here at MJT Net Ltd. Macro Scheduler was written to solve a pain I had at a previous job many years ago, and I still use it day in day out. Not only is it used for automating various business processes within the company, it is also used for creating small tools and for building parts of other projects.

But what struck me most about the coding horror article was this SawStop video:

It’s an impressive video. Perhaps the reason it struck a chord with me is that my father is a very keen woodworker and has a workshop full of very dangerous machinery which makes me wince every time I step inside. For some reason all I can think of when I watch him work is which limb is going to fly off first!

The creator actually did stick his own finger in a SawStop on camera, apparently on the Discovery Channel show Time Warp, but I can’t locate any web video of it.

Now, THAT is eating your own dogfood!

January 28, 2009

Macro Scheduler 11.1.02 Update

Filed under: Announcements — Marcus Tettmar @ 11:31 am

Macro Scheduler 11.1.02 Update is now available with the following fixes:

– Fixed: Access Violation when closing dialog editor if dialog has a MainMenu
– Fixed: Clicking “type a hotkey” checkbox in macro properties didn’t cause warning to save changes if nothing else changed
– Fixed: Compile Includes not including scripts specified with %SCRIPT_DIR% when compiled from Editor
– Fixed: Press End inside a SRT called End would fool the lexer into thinking the SRT ended at Press End
– Added: When typing SRT in editor, End is added automatically with SRT name.

Registered Downloads/Upgrades | Evaluation Downloads | New License Sales

January 27, 2009

Modal vs Non-Modal – Windows, Not Jazz

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

Every now and then, in the forums and in emails to us, there seems to be some confusion over what these terms mean.  As a developer I take these terms for granted, but anyone else, depending on their walk of life, might think they refer to some kind of Modal Jazz; something to do with a modal matrix used in linear algebra; or a type of auxiliary verb used to indicate modality.  

I sometimes need to remind myself that not everyone coming to Macro Scheduler and Windows Automation in general are familiar with geeky software terms.  I can’t tell you much about modal jazz, linear algebra or auxiliary verbs, but I can do my best to set to rest any confusion about Modal and Non-Modal windows.

Modal Windows

When a window is modal it remains active and focused until the user has finished with it and dismisses it.  While it is active no other windows of the same application can be activated.  A modal window is therefore normally a child window.  The user needs to interract with it before control can be returned to the parent application. In effect the parent application is locked and nothing proceeds until the modal window is closed.

You’ll find a good definition of Modal Windows on Wikipedia, here.

Non-Modal Windows

So a non-modal window is the opposite. While it is active you can still activate other windows. The user can switch between windows of the same application. The window being active does not prevent the rest of the application from continuing.

Modal Dialogs

In Macro Scheduler you can create custom dialogs. These can be modal or non-modal to the script. When we refer to a modal dialog what we mean is that once the dialog is displayed, the script halts until the user closes the dialog. Script execution is paused until the dialog is dismissed. The script cannot do any processing while the modal dialog is active. A modal dialog is displayed with the Show command, with a return variable specified, in which the “modal result” of the dialog is reported, corresponding to which button was pressed to close the dialog.

Non-Modal Dialogs

A dialog can be made to be non-modal. In which case the script carries on even after it has displayed the dialog. The user can interact with the dialog while the script continues to perform other tasks. The developer would need to write code to retrieve the state of the dialog and the data that has been entered into it. Usually this would need to take place in a loop. A non-modal dialog is displayed with the Show command, with the return variable omitted. Inside the loop we would retrieve the state and data of the dialog with the GetDialogAction command, and set it with ResetDialogAction.

In this post I have concentrated on definitions rather than going into detail on how you can create and control custom dialogs. That is a subject for another post and you will find more information in the help file and online help. Some dialog examples ship with Macro Scheduler and you’ll find more in the forums.

January 23, 2009

Screen Scraping with Macro Scheduler

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

What is Screen Scraping?

Screen Scraping is a term used to describe the process of a computer program or macro extracting data from the display output of another application.  Rather than parsing data from the database or data files belonging to an application, Screen Scraping pulls the data from the screen itself, extracting data that was intended to be displayed to the end-user as opposed to data designed for output to another application or database.  

Screen Scraping is necessary when there is a need to access the information displayed by the application but there is no method provided to access it behind the scenes.  The database or data files may not be accessible, or may be undocumented or proprietary and therefore cannot be parsed easily; the costs associated with interacting with the database may be too high; or the license agreement or warrenty prohibits it.  In the case of legacy systems that are no longer supported there may be no knowledge of the data structures, or the technology used is no longer compatible with current technology.  In these cases we are resorted to extracting the data from the screen – from the windows of the application.

The term Screen Scraping probably originates from the era of computer terminals when you could connect the terminal output of a computer to an input port on another and therefore record the screen data.  

Screen Scraping Methods

There are a number of ways we can retrieve information from the screen using Macro Scheduler, depending on the type of application the data is in.

Screen Scraping Web Applications

Applications like Macro Scheduler’s WebRecorder can access the data and objects inside an Interner Explorer window and can therefore be used to extract the data.  Technically speaking I would not call this screen scraping since WebRecorder is using an API interface provided by Internet Explorer, but the process of extracting information from web sites is commonly refered to as Screen Scraping.  With WebRecorder we can use the ExtractTag wizard to create code that extracts the text from a particular element in the page.   While WebRecorder is the easiest way to do it, it is also possible to automate IE and extract data from web pages by using VBScript. The following forum posts may help:

Automate Internet Explorer with OLE/ActiveX
Automate web forms with IE
HTTP GET and POST using VBscript

Screen Scraping Microsoft Office Applications

Microsoft Office Applications, like Internet Explorer, have a COM interface that allows scripts to manipulate them and access the data held within them.  Again, not really scraping data from the screen itself, as you are getting it directly from a programming interface.    There are a number of examples in the forums and blog archives and also some sample scripts that come with Macro Scheduler which demonstrate how to automate Office applications and retrieve data from them.  

Working with Excel

Screen Scraping Regular Windows Applications

Most other applications don’t offer a scripting interface like MS Office or Internet Explorer.  This is where we really need to work directly with the screen.   There are a number of ways we can do this kind of Screen Scraping with Macro Scheduler.

The Text Capture Functions

Macro Scheduler includes some Text Capture functions which can be used to extract text from a given window, rectangular screen area or screen point.  These functions use low level system hooks which monitor applications calling the various “TextOut” functions that Windows uses to output text to the screen.  By doing so they are able to capture this text.  The Text Capture functions return the text to  a variable which you can then use as needed.  

However, a few applications don’t use the Windows built-in functions to create and output text.  Don’t worry –Most do, but a few use their own techniques.  When you realise that text on the screen is just a sequence of small dots, if the application programmer decided to build his own routine to assemble text from dots rather than calling the Windows functions which already do that for you, you’re not going to be able to capture it.

The text capture functions and their limitations are explained here.  There is an example application, here, created with Macro Scheduler, which you can use to determine whether or not the text you want to capture can be captured using the text capture functions.

http://www.mjtnet.com/blog/2007/12/12/capturing-screen-text/
http://www.mjtnet.com/blog/2008/01/03/screen-scrape-text-capture-example/

Using the Clipboard for Screen Scraping

If the text you want to capture is selectable then you can use the clipboard to retrieve it.  A Macro Scheduler macro can send the keystrokes necessary to highlight and copy the text to the clipboard and then use the GetClipboard function to retrieve that text to a variable.  This is far less elegant than using the Text Capture functions but might be necessary if the application concerned is not utlising any of the Windows text out functions to create the text.

SetFocus>Notepad*
//Select ALL
Press CTRL
Send>a
Release CTRL
//Copy to clipboard
Press CTRL
Send>c
Release CTRL

//Get and display the data
WaitClipboard
GetClipboard>theData
MessageModal>theData

Screen Scraping via Optical Character Recognition

A final resort might be Optical Character Recognition (OCR). If the text is part of an image file neither the Text Capture or Clipboard methods are going to be able to extract it. But, depending on the quality of the image and the fonts used, OCR might. There are a number of OCR engines that can be used by Macro Scheduler, one of which is part of Microsoft Office. The following posts demonstrate how this can be done:

Screen OCR to Retrieve Otherwise Undetectable Text
Screen OCR – Recognising Graphical Text

More on Screen Scraping.