Perhaps you're familiar with such URL protocol handlers such as http://microsoft.com, ftp://user:pass@server  outlook:Contacts, file://http://www.coad.net/blog/images/Greenstone.bmp, ms-help://...

Want to make your own client-side URL handler?  Maybe to pull data from a source and display it, share content between applications, launch apps from web links, etc?

Say you want to be able to link from your intranet to special resources you know are on your internal network, or render data between applications via a central server across platforms and technologies.  This is one way to do some of that…

Sample Application
Here is a sample app that is designed to run registered applications on the local machine using a keyword.  After installing the example RunAppUrlProtocol app, you can put links on web pages like runapp://calc, runapp://excel, or runapp://docs that will trigger this app, look up the keyword, and execute the app.  You can install the app and then click the links to try it.

Registering the URL Protocol Handler
The key part here is the string value “URL Protocol” (with a blank value) which tells Windows to register this as a handler.

[HKEY_CLASSES_ROOT]

  [runapp]

     (Default) = "URL:RunApp Protocol Handler"

     URL Protocol = ""

     [DefaultIcon]

       (Default) = "c:\whatever\RunAppUrlProtocol.exe”

     [shell]

       [open]

          [command]

            (Default) = "c:\whatever\RunAppUrlProtocol.exe "%1""

The Code
Here is a sample app that demonstrates writing your own handler, RunAppUrlProtocol.zip.  The key elements here are:

  • This started as a Console Application that I changed the project properties to a Windows Application so that a console window isn’t opened up.  This allows the app to run “hidden”.
  • Grabbing the protocol from the command line args, so “runapp://excel” would be passed as a command argument.
  • The use of Regular Expressions here is trivial, but you can imagine it would be a lot more helpful when the URL is more complex, like the FTP URL with many optional components.  ftp://[<username>][:<password>]@<server>[:<port>][/<resource>]
  • This example has a minimal amount of user input checking, any decent app would have a lot more (for example, checking to make sure the target exists before trying to run it)
  • A good way to extend this example would be to add support for command line arguments in the URL, like runapp://<appkey>/<args>

#region Namespace Inclusions

using System;

using System.IO;

using System.Xml;

using System.Reflection;

using System.Diagnostics;

using System.Windows.Forms;

using System.Text.RegularExpressions;

#endregion

 

namespace RunAppUrlProtocol

{

   class Program

   {

      static void Main(string[] args)

      {

         // The URL handler for this app

         string prefix = "runapp://";

 

         // The name of this app for user messages

         string title = "RunApp URL Protocol Handler";

 

         // Verify the command line arguments

         if (args.Length == 0 || !args[0].StartsWith(prefix))

         { MessageBox.Show("Syntax:\nrunapp://<key>", title); return; }

 

         // Obtain the part of the protocol we're interested in

         string key = Regex.Match(args[0], @"(?<=://).+?(?=:|/|\Z)").Value;

 

         // Path to the configuration file

         string file = Path.Combine(Path.GetDirectoryName(

            Assembly.GetExecutingAssembly().Location), "RegisteredApps.xml");

 

         // Load the config file

         XmlDocument xml = new XmlDocument();

         xml.Load(file);

 

         // Locate the app to run

         XmlNode node = xml.SelectSingleNode(

            String.Format("/RunApp/App[@key='{0}']", key));

 

         // If the app is not found, let the user know

         if (node == null)

         { MessageBox.Show("Key not found: " + key, title); return; }

  

         // Resolve the target app name

         string target = Environment.ExpandEnvironmentVariables(

            node.SelectSingleNode("@target").Value);

 

         // Pull the command line args for the target app if they exist

         string procargs = node.SelectSingleNode("@args") != null ?

            node.SelectSingleNode("@args").Value : "";

 

         // Start the application

         Process.Start(target, procargs);

      }

   }

}

References