Monday, August 13, 2012

Spawning Windows On-Screen Keyboard (OSK) in WPF

During a recent project, I needed to be able to fire up the Windows 7 On-Screen Keyboard (OSK) utility from my application, which runs in kiosk mode. The application works mostly through touch gestures, but on certain steps users are required to enter text.

For starters, the straight forward way to do this is to simply start the external application process in the following way: If you need to run an external tool from a simple program, you can just add that calling line in your main program method:

Now, in this case, the main Kiosk application had a dependency with legacy unmanaged code, which required the app to target x86 processors (32-bit platforms). This is generally not an issue since Windows is able to run 32-bit apps on either 32-bit or 64-bit platforms.
The problem I had was that I could not spawn a 64-bit external app from a 32-bit application directly. Whenever I tried to fire up the OSK from my app I got an error saying that the OSK could not be launched.

image

The problem arises because Windows 64-bit has two versions of the OSK utility, one for 32-bit and one for 64-bit. My app, targeting a 32-bit platform was making the call, but since it was running on a 64-bit machine, Windows was handling the calling event and routing it to the 64-bit version of the OSK, which causes the error.

Since I could not switch the main app to target any CPU (both 32-bit and 64-bit platforms), I needed a work around to be able to run the OSK from my app. It turns out to be easier than I thought.

You need to create a secondary .net app targeting any CPU platform which is the one in charge of firing up the OSK. You can do this by creating a simple console application with the code I put above, but you will get the black console app screen when it runs, which is not ideal. Instead, you can create a simple Windows Forms application and take out the forms and just leave the main program with the Main() method. As you can see, the code to fire the OSK will be exactly the same, but you won’t see any black screen popping up.

clip_image002

Once you have the secondary app in place (make sure it works by running it a couple of times), just copy the executable to wherever your main app needs it. Then you can create a static utility class in your main app with a couple of methods to fire up and close the OSK.

Here’s the complete code to do so: Notice that the code is able to close the OSK process if it is already running without issues. It’s just firing up the OSK app that needs to use the secondary app. You just need to make sure that the OSK is not running before trying to fire it up and before attempting to close it. Remember to change the “YourKeyboardManagerAppPath” for the actual path where your keyboard utility app lives.

The nice thing about this workaround is that it effectively shows you how to fire third party apps from your main app, and how to use a secondary application as a bridge to fire up other apps if you have any problems doing so from your main app.

clip_image004

You can find a sample app setup with the complete code here.
Cheers!

No comments:

Post a Comment