Skip to content

Instantly share code, notes, and snippets.

@davecluderay
Last active August 29, 2015 14:04
Show Gist options
  • Save davecluderay/f306de1131189b70d3ce to your computer and use it in GitHub Desktop.
Save davecluderay/f306de1131189b70d3ce to your computer and use it in GitHub Desktop.
Handles kiln:// URLs, translating them into the full http(s) form before executing them.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Microsoft.Win32;
namespace KilnUrlHandler
{
public class Program
{
public static void Main(string[] args)
{
try
{
if (args.Length < 1)
{
RegisterForKilnScheme();
return;
}
var pattern = new Regex("^kiln://(?<Path>.+)$", RegexOptions.IgnoreCase);
var match = pattern.Match(args[0]);
if (!match.Success)
{
return;
}
var kilnUrl = GetKilnUrl();
if (kilnUrl == null) return;
var path = match.Groups["Path"].Value;
var fullUri = new Uri(kilnUrl, path);
Process.Start(fullUri.AbsoluteUri);
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, "Kiln URL Handler", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
private static void RegisterForKilnScheme()
{
string executablePath = GetExecutablePath();
Registry.SetValue("HKEY_CURRENT_USER\\Software\\Classes\\kiln",
"",
"URL: Kiln Scheme");
Registry.SetValue("HKEY_CURRENT_USER\\Software\\Classes\\kiln",
"URL Protocol",
"");
Registry.SetValue("HKEY_CURRENT_USER\\Software\\Classes\\kiln\\DefaultIcon",
"",
string.Format("\"{0}\"", executablePath));
Registry.SetValue("HKEY_CURRENT_USER\\Software\\Classes\\kiln\\shell\\open\\command",
"",
string.Format("\"{0}\" \"%1\"", executablePath));
}
private static string GetExecutablePath()
{
return new Uri(Assembly.GetEntryAssembly().CodeBase).LocalPath;
}
private static Uri GetKilnUrl()
{
string profileDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string[] mercurialIniFiles = Directory.GetFiles(profileDirectory, "mercurial*.ini");
foreach (var mercurialIniFile in mercurialIniFiles)
{
var buffer = new StringBuilder(1024);
uint result = GetPrivateProfileString("schemes", "kiln", "", buffer, (uint)buffer.Capacity, mercurialIniFile);
if (result == 0)
{
int lastError = Marshal.GetLastWin32Error();
if (lastError != ErrorSuccess && lastError != ErrorNoToken && lastError != ErrorFileNotFound)
throw new Win32Exception(lastError);
continue;
}
var url = buffer.ToString();
if (Uri.IsWellFormedUriString(url, UriKind.Absolute))
{
if (!url.EndsWith("/")) url += "/";
return new Uri(url, UriKind.Absolute);
}
}
return null;
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern uint GetPrivateProfileString(string lpAppName,
string lpKeyName,
string lpDefault,
StringBuilder lpReturnedString,
uint nSize,
string lpFileName);
private const int ErrorSuccess = 0;
private const int ErrorFileNotFound = 2;
private const int ErrorNoToken = 1008;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment