Register a Custom URL Protocol Handler


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

Comments (20)

  1. noahc says:

    Arnaud,

    Thanks for letting me know!  I’ve fixed the link in the post.

  2. Joe says:

    Do you know if there are size limitations  – we have been having problems with IE not calling the application when you have larger arguments – or maybe its invalid characters? Not sure.

    Any ideas?

  3. delux says:

    any chance you know how to detect from within the html code if a particular protocol is registered?

    if( my_proto_registered() )

       navigate_to("my_proto://target");

    else

       document.write("<a href=install.exe> install first </a>");

  4. celine says:

    Is it possible to detect in a web page (html, javascript…) whether a protocol is registered by an application ? see delux comment

  5. brien says:

    re: detect if the protocol is registered —   one idea I’ve been exploring is to install noop plugins in FF and IE. A script can act on whether a plugin is present or not … it’s indirect, but functional …

  6. jetzhong83@yahoo.com.cn says:

    hello, I want ask a question. At what kinds of situation, custom URL protocl can not work. (such as the local security policy or something else)

  7. fabien says:

    this works well on web page.

    if you enter runapp://calc in an outlook mail, it won’t detect it as a custom url. You need to insert an hyperlink to make it work. Do you have a way of telling outlook that runapp: is a valid url ?

  8. Fred says:

    After installing RunAppUrlProtocol, runapp://calc/ and runapp://docs/ work as advertised, but runapp://excel/ causes an exception where windows reports the problem and says RunAppUrlProtocol needs to close.  Here are the contents of the Error Signature:

    EventType : clr20r3     P1 : runappurlprotocol.exe     P2 : 1.0.0.0     P3 : 453792e0     P4 : system     P5 : 2.0.0.0     P6 : 461ef191     P7 : 3916  P8 : 288     P9 : system.componentmodel.win32

  9. Kalle says:

    There is a small tool that helps you register custom url protocols at http://www.codeplex.com/customurl . This tool is free and open source.

  10. TacoMe says:

    nice guide but it doesn’t for me :

    I need to set a operating path for the application I want to use. Is there a way to do this?

  11. surya says:

    how to make runapp://calc a clickable hyperlink in IM

    (Office Communicator)

  12. John Saunders says:

    Do registered protocol handlers work with all browsers?

  13. ndoung says:

    I did the same when registering my desktop application to a custom URL protocol. My application is JAVA application wrapped with executable (e.g. myapp.exe). It works for firefox, but not IE. I get Application Not Found dialog when enter my custome URL in the URL address field in IE (e.g. myapp:arg1). Any idea?

  14. Mehran says:

    I have installed my protocol as you explained . but it doesn't works .

    I wrote this code :

    "<a href="MyApp:HelloThere">Click</a>"

    but after click , this message will be shown : "Firefox doesn't know how to open this address , because the protocol (myapp) isn't associated with any ptogram"

    why ?

  15. Hwanime says:

    Thank you for sharing about "Register a Custom URL Protocol Handler" useful problem ! Should be thinking.

    http://www.designerhandbagsoutletus.com

  16. Jozeda says:

    You need to insert an hyperlink to make it work.http://www.designerhandbagsoutletus.com

  17. Jason Harrison says:

    Does this still work in Windows 7 and Windows 8?

  18. oshanz says:

    Thanks for the article. it works nice with my app.

    i need to parse json to my application. currently it works for jsons with length below around 2000 chars(i feel this may be the reason support.microsoft.com/…/830473).

    but i need to parse more data. how can i do that.

    now i use javascript function to call on button click.

    document.location.href = 'myapp://' + encodeURIComponent(json);

    i found that Data URI shema support large data. (en.wikipedia.org/…/Data_URI_scheme)

    document.location.href  = ('data:text/html;charset=utf-8,' + encodeURIComponent(json));

    i googled, but i couldn't found a way to call my app.  it need MIME type.

    Please Help.

  19. James says:

    Do you have something like this that would work in VB.Net, I need to have the form pull data from MySQL based on an id passed to it like so "custid://612"  not finding much at all on the internet…