Launching a Smart Client from the Web - With Context!
SharePoint interest is growing with leaps and bounds, but there are still many scenarios that make more sense to leave in rich client applications. The question I've been asked a lot lately is how to bring these two worlds closer together.
Say, for example, you've got a web page that displays some basic information about a customer. How can you create a hyperlink that launches a smart client and takes you to that same customer inside the application? The solution is probably easier than you suspect, and in this post I'll walk through the steps.
The method we'll use to transfer context between the web site and our application is a simple file. I refer to these files 'Launch Files' and the real trick is getting windows to open our application when it sees them instead of prompting the user to save to disk.
You may not realize it but you've probably seen this before. Outlook does this with V-Card, V-Calendar and ics files. It's the same mechanism that allows you to subscribe to a SharePoint calendar in Outlook with a single click. (In truth it's 2 clicks in Vista because UAC asks the user if it's OK to send data to the app. But that's a topic for another day.)
The Launch File
The first thing you need to do is determine the structure for your launch file. I recommend XML because it's easy to generate and the format can grow with your application over time. You can place any data you want in this file, but keep in mind that it serves as context between your web site and your smart client.
In most cases you'll probably want to generate this file procedurally using query string parameters. This allows easy integration with the rest of your site, and a launch URL might look something like this:
AppLauncher.aspx could look at the AppType parameter to determine which XML schema and file extension to use. The remaining parameters (CustomerNumber in this example) could be used to determine which data to include in the generated file.
File Extensions and Associations
Once you've determined the file format you need to settle on a unique file extension. It doesn't really matter what the extension is, it just has to be unique. This is no different than files intended for the local disk.
With the extension in mind, next you need to modify your application installer to include the new file type. The file type association registry keys are where you instruct Windows to launch your application whenever it sees a link for your file. Here's an example screenshot from a setup project in Visual Studio:
BrowserFlags 0x8 or 0x9 indicates that a particular app should open in its own window when its associated file is clicked (as opposed to opening within IE).
EditFlags indicates what explorer should do with a particular file type and/or defines what class it is. 0x10000 turns off the "Confirm open after download" box in IE. If this flag is set, the file will be automatically downloaded to the browsers temporary folder and its 'open' verb will be executed.
For more details, read the File Types article on MSDN.
Existing Application Instances
The next thing you want to consider is what to do if the application is already running. By default, the registry settings above will simply start another instance of your application. Instead, you probably want to notify an existing instance. That's why in the screenshots below you will see the 'open' verb is associated with a DDE command (ddeexec). If the application is not already running, Windows starts it before the DDE command is sent.
In this example, Windows will send the DDE command [Import("<FilePath>")] . The Application and Topic names are flexible, but you'll want to filter on them later.
Unfortunately, .Net doesn't have built-in support for handling DDE messages and DDE can seem a bit complex. I wrote a managed wrapper class for dealing with this some time ago and you can get it here:
Net DDE. I'm including this for sample purposes only and it doesn't come with any kind of warranty. :)
Here's an example of how to use DDE Client. The application entry point looks something like this:
static void Main()
// Create DDE client
dde = new DDEClient();
// Filter on app name
dde.AppName = "Cartographer";
// Start listening for DDE messages
dde.Execute += new DDEExecuteHandler(dde_Execute);
// Run application as normal
And the DDE message handler looks something like this:
private static void dde_Execute(DDEClient sender, DDECommand commands)
// We only pay attention to the first command
DDECommand command = commands;
// The only command we support is Import.
if (command.Name != "Import") return;
// Get the launch file path
string launchFilePath = command.Params;
// TODO: Open the launch file and do something
I hope this helps, and happy coding.