Page 1 of 5
Automating applications using messages
There are lots of programs that for one reason or another don’t have any scripting facilities. Some, like Outlook Express, don’t support scripting because there is an alternative version which you can buy, i.e. Outlook, which does. In other cases the reason is more to do with the time and effort involved in adding scripting support and this is the reason that many free and open source applications lack scripting.
Sometimes this doesn’t matter too much but when you find yourself using an otherwise good program in exactly the same way repeatedly you really do miss the ability to automate the task. The good, and perhaps surprising, news is that you can add scripting to almost any application (usually not the most modern based on WPF .NET tecnology) without needing access to its source code. This project demonstrates how to use very basic Windows mechanisms to gain control of an application. The technique is based on knowing how Windows really works and while this could be seen as advanced it’s all surprisingly easy for such a powerful set of tools which have a lot of uses.
In this project we use the .NET framework to do the job and program in C# but the principles generalise to any language that has acess to the the Windows API.
DVD to MPEG
To demonstrate how everything works I’m going to automate a simple task in an application called VOBedit – which you can find by typing its name into a search engine, or by downloading the code of this project from the codebin.
This is a freeware program that can be used to edit the video VOB files found on a DVD. A VOB file is essentially an MPEG 2 file with MPEG 2 and audio interleaved or multiplexed. If you want to edit the video, then the simplest thing to do is to demultiplex the VOB files into a single MPGEG 2 video file and a single, usually AC3 coded, audio file.
This is one of the things VOBedit does for you but you have to click the Open button, manually select the first VOB file in the dialog box that appears, click Open, select the “demux” button, specify what you want demuliplexed and specify where the files are to be stored. Not a difficult task but very boring if you have to repeat it for lots of DVDs – hence the need for automation.
Notice that while VOBedit is the program used as the example the ideas and methods are fairly general and represent a way of tackling the automation of any program.
Getting the message
Although it’s something that nowadays is well hidden beneath layers of software, Windows is a message-passing operating system. All of the controls, buttons, textboxes and so on that you see are also just specialised windows and these communicate with one another by sending messages. For example, when you click a button the button generates a message which is passed to its parent window which can then perform some action in response to the click.
Windows messages come in a huge range of types and there are so many generated in a typical system that the majority of them are simply ignored by the windows that receive them! Today we think about interactions between components as “events” and write event handlers but the messages are still there and still doing the same job in the same way.
Why is it important to know and understand the Windows messaging system?
The simple answer is that it isn’t if you are happy working with events, but direct access to messages is something that is easy to implement and it opens up some remarkable abilities. For example, you can quite easily send a message from one application to another. Notice that this means that a message can cross “process boundaries”, something that is very difficult to do by other means. In particular it isn’t difficult to arrange to send a message to a window which informs it that a button that it hosts has just been clicked. Similarly you can send messages that set and get the text in textboxes and other standard controls that belong to other applications running on your PC. Clearly this is very powerful stuff.
Send and Notify
There is only minimal support for messaging built into the .NET framework. To include it would be a huge security risk but there is nothing stopping you from using the original Windows messaging API via P/invoke. There are two key API calls that allow you to send messages to other applications, SendMessage and SendNotifyMessage which have to be defined at the start of you application as:
CharSet = CharSet.Auto,
SetLastError = false)]
public static extern IntPtr SendMessage(
HandleRef hWnd, uint Msg,
IntPtr wParam, IntPtr lParam);
SetLastError = true,
CharSet = CharSet.Auto)]
public static extern bool
HandleRef hWnd, uint Msg,
IntPtr wParam, IntPtr lParam);
Both use the same set of parameters to send a message but SendMessage waits until the target window has accepted and processed the message and SendNotifyMessage just drops the message off into the message queue and returns at once.
A message is specified by four parameters:
- hWnd – the “handle” of the window that the message is to be sent to
- Msg – an unsigned 32-bit value indicating the type of message
- wParam – a 32-bit value usually but not always specifying the sender of the message
- lParam – a 32 bit value specifying other features of the message
Notice that a “handle” is just a way of keeping track of objects across process boundaries. For example every window has a “window handle” that identifies it uniquely.
As already mentioned, there are thousands of different message types but the good news is that we can do nearly everything we need with just a small number.