Introduction
This article is the third in row of my CodeProject articles on automation of unmanaged Windows GUI applications with no exported program interface ("black box" applications). These applications are referred to below as target applications. While using the same injection technique, the articles present different ways of communication between injected code and outside world.
Background
The suggested technique transforms target application to an automation server, i.e., its clients (subscribers) running in separate processes are able to control target application and get some of its services either in synchronous or asynchronous (by receiving event notifications) modes. In the previous articles [1] and [2], this transformation was described in detail with appropriate code samples. So here only a brief overview is given.
The course of actions for the transformation is as follows:
- A piece of foreign code is injected into target application using the remote thread technique [3];
- The injected code subclasses windows of target application adding desirable [pre]processing for Windows messages received by subclassed windows;
- A COM object is created in the injected code in context of target application process. This object is responsible for communication of automated target application with the outside world.
The above steps are common for all three articles. The main difference lays in the nature and composition of the COM object operating inside the target application. In the earliest article [1], the communication object was an ordinary COM object self-registered with Running Object Table (ROT). It supports direct interface for inbound calls and outgoing (sink) interface for asynchronous notification of its subscribers. Such objects provide duplex communication with several subscriber applications (both managed and unmanaged) machine-wide but cannot support communication with remote subscriber applications since ROT is available only locally.
The communication object of the next generation [2] constitutes COM Callable Wrapper (CCW) around managed WCF server component. This allows automated target application to be connected to both local and remote subscribers, thus considerably expanding access range of newly formed automation server. But this advanced communication object still has limitation: it enables only remote subscribers locating in the same Local Area Network (LAN). Subscribers outside the LAN are banished by firewall and lack of permanent IP address of target application machine. It means that if I automate a GUI application on my home desktop, then my daughter and my dog can utilize its services from their machines at home (within the same LAN), whereas a friend of mine is deprived of such pleasure in his/her home (outside my LAN).
Azure AppFabric Service Bus
This is where the Microsoft Azure platform [4] comes to the rescue. Among other useful things it offers AppFabric Service Bus, technology and infrastructure enabling connection between WCF aware server and client with changeable IP addresses locating behind their firewalls. Since dynamic IP address and firewall are obstacles for inbound calls and transparent for outbound calls, Service Bus acts as Internet-based mediator for client and server outbound calls.
It turned out that to make automated target application available world-wide with Azure Service Bus is amazingly simple. Taking software in the article [2] as my departure point, I found that no change in code is required (well, actually I did change code a little, but this change was not compulsory). Actually three actions should be carried out:
- Open account for Windows Azure AppFabric Service Bus and create a service namespace (see MSDN or e.g. [5], chapter 11)
- Install Windows Azure SDK on both target application and client machines, and
- Change configuration files for both target application and client.
New configuration files are needed because usage of Service Bus implies special Relay binding with appropriate security setting and special endpoint behavior enabling Service Bus connection. In our sample, netTcpRelayBinding
is used. Endpoint behavior provides issuerName and issuerSecret parameters for Service Bus connection. Both of them should be copied from your Azure AppFabric Service Bus account. From the same account, mandatory part of WCF service base addresses should be copied:
sb://SERVICE-NAMESPACE.servicebus.windows.net
(SERVICE-NAMESPACE
placeholder should be replaced with your service namespace). Details of configuration files can be seen in the sample.
Code Sample
Like in the previous articles, well known Notepad text editor is taken as target application for automation. Console application InjectorToNotepad.exe injects NotepadPlugin.dll into target application with the remote thread technique using Injector.dll COM object. The injected NotepadPlugin subclasses both frame and view windows of Notepad and creates NotepadHandlerNET managed component in COM Callable Wrapper (CCW). NotepadHandlerNET is responsible for communication with outside world. This technique was explained in full details in my previous article [2].
Build and Run Sample
- Run Visual Studio 2010 as administrator and open NotepadAuto.sln.
- Open Solution Property Pages, select Multiple startup projects, set for projects
InjectorToNotepad
and AutomationClientNET
Action attribute to Start and press OK button. - In App.config files of
NotepadHandlerNET
and AutomationClientNET
projects, replace values of issuerName and issuerSecret attributes in <sharedSecret>
tag and placeholder SERVICE-NAMESPACE
with appropriate values of your Azure AppFabric Service Bus account. - Build and run the solution.
Output of projects will be placed in Release or Debug (according to your built choice
) working directory
. InjectorToNotepad application will copy
Notepad.exe to the same directory, and fancy configuration file
Notepad.exe.config is created during the build.
InjectorToNotepad console application runs Notepad from working directory and should report SUCCESS! However it takes some time before word [AUTOMATED] will appear in caption of the Notepad frame window. Then press big button tagged with "Bind to Automated Notepad via Azure Service Bus". Binding takes time (up to 30 sec). On its completion, the big button becomes disabled and three smaller operation buttons get enabled. Please see Test Sample section to perform test.
Run Demo
Demo contains two directories, namely, Injector and Client. The Injector directory should be placed on the target application machine. It contains all components required for injection to Notepad target application. The Client directory should be placed on client (subscriber) machines.
Before starting sample, please install Windows Azure SDK on both target application and client machines. Replace in configuration files Notepad.exe.config and AutomationClientNET.exe.config values of issuerName and issuerSecret attributes in <sharedSecret>
tag and placeholder SERVICE-NAMESPACE
with appropriate values of your Azure AppFabric Service Bus account. Please note that cmd and exe (except for target application Notepad) files should be run as administrator. Make sure that you have stopped your software protecting applications from injection (since this protective software considers any injection as malicious action).
First run COMRegisteration.cmd command file. It registers COM components WindowFinder.dll and Injector.dll with regsvr32.exe utility and CCW for NotepadHandlerNET.dll with regasm.exe utility. Then run InjectorToNotepad.exe console application. It copies Notepad.exe from system to working directory (for successful operation of injected COM object Notepad should run from working directory) and performs injection. It takes some time after injector prints message SUCCESS! before Notepad will show word [AUTOMATED] in its caption. InjectorToNotepad.exe console application may be closed. Now our Notepad target application is automated and ready to serve its clients.
From Client directory (that can be placed on any machine world-wide), run AutomationClientNET.exe client application and press big button "Bind to Automated Notepad via Azure Service Bus" on it. It takes some time (app. 30 sec) before the client binds to automated Notepad. If the binding succeeds, the big button becomes disabled while operation buttons get enabled.
Test Sample
Now the sample is ready for test. You may open Notepad's Find dialog, add custom menu item by pressing appropriate buttons of the client application. You may type some text in Notepad and copy it to clients by pressing client's "Copy Text" button. To test asynchronous action, type some text in Notepad followed by a sentence conclusion sign (".", "?", or "!"). Text typed will be reproduced in an edit box of client application.
You may test the sample for several clients. For this, you have to make sure that URI of each client is unique. So in AutomationClientNET.exe.config file of another AutomationClientNET.exe client application, replace suffix of its service base address from /Subscriber1 to, say, /Subscriber2, start this new client and bind it to automated Notepad. All active clients get copied text and asynchronous events when text typed in Notepad is concluded with ".", "?", or "!".
Discussion
The described approach shows great usefulness of Azure AppFabric Service Bus for automation of desktop applications. The Service Bus allows automated application to serve its clients world-wide overcoming firewall and dynamic IP address limitations, and this is achieved without additional code. The Service Bus may be used as a mediator between any kind of automated applications and their clients.
In the sample for the article, the target application and its clients communicate only via Service Bus. In real world automation, different endpoints should be provided for local client, clients located in the same Local Area Network (LAN) and for "distant" remote clients. Service Bus endpoints should be of hybrid type allowing the most efficient way for communication with each client.
Conclusion
The article presents evolution of a technique for automation of Windows applications with injected objects. A .NET WCF equipped component inside unmanaged target process provides communication between automated application and its clients via Azure AppFabric Service Bus. This approach overcomes such obstacles as firewalls and dynamic IP addresses on both sides making automation server available world-wide.
References
[1] Igor Ladnik. Automating Windows Applications. CodeProject.
[2] Igor Ladnik. Automating Windows Applications Using the WCF Equipped Injected Component. CodeProject.
[3] Jeffrey Richter, Christophe Nasarre. Windows via C/C++. Fifth edition. Microsoft Press, 2008.
[4] Roger Jennings. Cloud Computing with the Windows Azure Platform. Wiley Publishing, 2009.
[5] Juval Lowy. Programming WCF Services. Third edition. O'Reilly, 2010.
History
- 12th November, 2010: Initial version