2
using System;
using System.Windows.Forms;
using Microsoft.Win32;

namespace Aodb
{
    internal static class AodbProtocol
    {
        private const string _Protocol = "aodb";
        private const string _ProtocolHandler = "url.aodb";

        private static readonly string _launch = string.Format(
            "{0}{1}{0} {0}%1{0}", (char)34, Application.ExecutablePath);

        private static readonly Version _win8Version = new Version(6, 2, 9200, 0);

        private static readonly bool _isWin8 =
            Environment.OSVersion.Platform == PlatformID.Win32NT &&
            Environment.OSVersion.Version >= _win8Version;

        internal static void Register()
        {
            if (_isWin8) RegisterWin8();
            else RegisterWin7();
        }

        private static void RegisterWin7()
        {
            var regKey = Registry.ClassesRoot.CreateSubKey(_Protocol);
            regKey.SetValue(null, "URL:aodb Protocol");
            regKey.SetValue("URL Protocol", "");

            regKey = regKey.CreateSubKey(@"shell\open\command");
            regKey.SetValue(null, _launch);
        }

        private static void RegisterWin8()
        {
            var regKey = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Classes")
                .CreateSubKey(_ProtocolHandler);

            regKey.SetValue(null, _Protocol);

            regKey.CreateSubKey("DefaultIcon")
                .SetValue(null, string.Format(
                    "{0}{1},1{0}", "\"", Application.ExecutablePath));

            regKey.CreateSubKey(@"shell\open\command").SetValue(null, _launch);

            Registry.LocalMachine.CreateSubKey(string.Format(
                @"SOFTWARE\{0}\{1}\Capabilities\ApplicationDescription\URLAssociations",
                Application.CompanyName, Application.ProductName))
                .SetValue(_Protocol, _ProtocolHandler);

            Registry.LocalMachine.CreateSubKey(@"SOFTWARE\RegisteredApplications")
                .SetValue(Application.ProductName, string.Format(
                    @"SOFTWARE\{0}\Capabilities", Application.ProductName));
        }

        internal static void Unregister()
        {
            if (!_isWin8)
            {
                Registry.ClassesRoot.DeleteSubKeyTree("aodb", false);
                return;
            }

            // extra work required.
            Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Classes")
                .DeleteSubKeyTree(_ProtocolHandler, false);

            Registry.LocalMachine.DeleteSubKeyTree(string.Format(@"SOFTWARE\{0}\{1}",
                Application.CompanyName, Application.ProductName));

            Registry.LocalMachine.CreateSubKey(@"SOFTWARE\RegisteredApplications")
                .DeleteValue(Application.ProductName);
        }
    }
}

the above class was pieced together from snippets of code I found on the net, specifically:

http://dotnet-snippets.com/snippet/register-user-defined-url-protocol/2707 <-- works for Win7 but not Win8

which led me to find Registering a protocol handler in Windows 8 which is an unconfirmed answer.

HOWEVER, I can't get the URL protocol to work in Win8; clicking an aodb://1234 hyperlink does not launch the application and the web browser complains that the protocol isn't supported, and I believe the above article is not a proper answer.

does anyone who has knowledge of protocol handlers, know where I went wrong in the above code and why the protocol doesn't register in win8? I can see the above code worked by looking at the registry keys in regedit, but for some reason, the protocol isn't recognized.

Community
  • 1
  • 1
Xyphos
  • 215
  • 2
  • 8
  • Look like you have to remove this line `if (!_isWin8) return;`, run your app, then restart your browser if it work. – NoName Feb 25 '16 at 11:37
  • that part is for Win7 version, the registry key is split in the beginning by an unary operator. – Xyphos Feb 25 '16 at 11:46
  • in the [link](http://stackoverflow.com/questions/13559915/registering-a-protocol-handler-in-windows-8) you post, they write this registry, but you dont: `HKLM\SOFTWARE\MyApp\Capabilities\ApplicationDescription\URLAssociations myprotocol = MyApp.ProtocolHandler //Associated with your ProgID` – NoName Feb 25 '16 at 11:51
  • yeah that didn't work either. it's odd. `Registry.LocalMachine.CreateSubKey(string.Format( @"SOFTWARE\{0}\Capabilities\ApplicationDescription\URLAssociations", Application.ProductName)) .SetValue("aodb", string.Format(@"{0}.aodb", Application.ProductName));` – Xyphos Feb 25 '16 at 11:55
  • Your code don't work because any registry use in Win7 you remove from win8. – NoName Feb 25 '16 at 12:04
  • because the article shows that the registry location changed in win8 so the unary operator in the begining changes the location. the code works because I can see the registery keys in regedit - I just don't know why the protocol isn't registering in the browser – Xyphos Feb 25 '16 at 12:12
  • Why don't you just tried follow exactly what the guy in the link say? It is nothing harm your computer and you can easily undone it. – NoName Feb 25 '16 at 12:14
  • Check your registry for what is actually registered. I think it's your `_launch = string.Format(...)` code, it seems to unnecessarily add backslashes to the path. – CodeCaster Feb 25 '16 at 13:47
  • that's an escaped quote, not a slash. I'll edit for readability – Xyphos Feb 25 '16 at 13:49

1 Answers1

7

I GOT IT! Finally. Ok, it seems that you have to implement both Win7 and Win8 registry functions for Win8 and above, but Win7 doesn't require the extra code. below is the final class for registering a custom protocol.

using System;
using System.Windows.Forms;
using Microsoft.Win32;

namespace Aodb
{
    internal static class AodbProtocol
    {
        private const string _Protocol = "aodb";
        private const string _ProtocolHandler = "url.aodb";

        private static readonly string _launch = string.Format(
            "{0}{1}{0} {0}%1{0}", (char)34, Application.ExecutablePath);

        private static readonly Version _win8Version = new Version(6, 2, 9200, 0);

        private static readonly bool _isWin8 =
            Environment.OSVersion.Platform == PlatformID.Win32NT &&
            Environment.OSVersion.Version >= _win8Version;

        internal static void Register()
        {
            if (_isWin8) RegisterWin8();
            else RegisterWin7();
        }

        private static void RegisterWin7()
        {
            var regKey = Registry.ClassesRoot.CreateSubKey(_Protocol);

            regKey.CreateSubKey("DefaultIcon")
                .SetValue(null, string.Format("{0}{1},1{0}", (char)34, 
                    Application.ExecutablePath));

            regKey.SetValue(null, "URL:aodb Protocol");
            regKey.SetValue("URL Protocol", "");

            regKey = regKey.CreateSubKey(@"shell\open\command");
            regKey.SetValue(null, _launch);
        }

        private static void RegisterWin8()
        {
            RegisterWin7();

            var regKey = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Classes")
                .CreateSubKey(_ProtocolHandler);

            regKey.SetValue(null, _Protocol);

            regKey.CreateSubKey("DefaultIcon")
                 .SetValue(null, string.Format("{0}{1},1{0}", (char)34,
                     Application.ExecutablePath));

            regKey.CreateSubKey(@"shell\open\command").SetValue(null, _launch);

            Registry.LocalMachine.CreateSubKey(string.Format(
                @"SOFTWARE\{0}\{1}\Capabilities\ApplicationDescription\URLAssociations",
                Application.CompanyName, Application.ProductName))
                .SetValue(_Protocol, _ProtocolHandler);

            Registry.LocalMachine.CreateSubKey(@"SOFTWARE\RegisteredApplications")
                .SetValue(Application.ProductName, string.Format(
                    @"SOFTWARE\{0}\Capabilities", Application.ProductName));
        }

        internal static void Unregister()
        {
            if (!_isWin8)
            {
                Registry.ClassesRoot.DeleteSubKeyTree("aodb", false);
                return;
            }

            // extra work required.
            Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Classes")
                .DeleteSubKeyTree(_ProtocolHandler, false);

            Registry.LocalMachine.DeleteSubKeyTree(string.Format(@"SOFTWARE\{0}\{1}",
                Application.CompanyName, Application.ProductName));

            Registry.LocalMachine.CreateSubKey(@"SOFTWARE\RegisteredApplications")
                .DeleteValue(Application.ProductName);
        }
    }
}
Xyphos
  • 215
  • 2
  • 8
  • Registry.ClassesRoot.DeleteSubKeyTree("aodb", false); change to Registry.ClassesRoot.DeleteSubKeyTree(_Protocol, false); – Mightywill Mar 26 '23 at 15:45