If you want to jump straight into the code go here: https://github.com/arunjeetsingh/SampleCode/tree/master/UniversalAppLaunchingWPFApp
In my last post I talked about launching a Universal Windows App from a WPF app. Today, we go the other way around. Not many people are aware of this but Windows has had support for custom protocol schemes (mailto:, ftp:, skype: are good examples) aka deep linking since about 1996. In fact, the Internet Explorer team introduced the idea in the Platform Developers Conference of ’96. I even talked about it during my Build session here.
What does that mean for us? Well, it means that practically any app can sign up for a custom scheme. That includes apps written in Windows Presentation Foundation (WPF), WinForms, plain old Win32 and even Visual Basic. All an app developer has to do is create a specific set of registry entries to let Windows know that they would like to handle a custom scheme. Of course, if you’re writing a universal app you can simply put that information in your manifest and we’ll take care of creating the registry entries. In this blog post, we will learn how to create a WPF app that registers for a custom scheme. We will then see an example of a universal app that launches the WPF app we created using the custom scheme. Let’s get started!
To follow along, clone the repository at https://github.com/arunjeetsingh/SampleCode and open the solution at UniversalAppLauncherWPFApp\UniversalAppLaunchingWPFApp.sln.
Creating the WPF Protocol Handler
The WPFProtocolHandler project is a simple WPF app. All of the interesting code lives in the MainWindow.xaml.cs file. The first piece of code that warrants our attention is the code that installs a protocol handler. Before you click that button, know that the code requires admin privileges to run. The best way I found to accomplish this was to simply start WPFProtocolHandler.exe as administrator and then install the protocol. Here’s what we do to install a protocol handler:
private void InstallProtocol_Click(object sender, RoutedEventArgs e)
{
using (var hkcr = Registry.ClassesRoot)
{
if (hkcr.GetSubKeyNames().Contains(SchemeName.Text))
{
MessageBox.Show(string.Format(“Looks like {0} is already installed.”, SchemeName.Text));
return;
}
using (var schemeKey = hkcr.CreateSubKey(SchemeName.Text))
{
//[HKEY_CLASSES_ROOT\com.aruntalkstech.wpftarget]
//@=”Url:WPF Target Protocol”
//”URL Protocol”=””
//”UseOriginalUrlEncoding”=dword:00000001
schemeKey.SetValue(string.Empty, “Url: WPF Target Protocol”);
schemeKey.SetValue(“URL Protocol”, string.Empty);
schemeKey.SetValue(“UseOriginalUrlEncoding”, 1, RegistryValueKind.DWord);
//[HKEY_CLASSES_ROOT\com.aruntalkstech.wpf\shell]
using (var shellKey = schemeKey.CreateSubKey(“shell”))
{
//[HKEY_CLASSES_ROOT\com.aruntalkstech.wpf\shell\open]
using (var openKey = shellKey.CreateSubKey(“open”))
{
//[HKEY_CLASSES_ROOT\com.aruntalkstech.wpf\shell\open\command]
using (var commandKey = openKey.CreateSubKey(“command”))
{
//@=”C:\\github\\SampleCode\\UniversalAppLaunchingWPFApp\\WPFProtocolHandler\\bin\\Debug\\WPFProtocolHandler.exe \”%1\””
commandKey.SetValue(string.Empty, Assembly.GetExecutingAssembly().Location + ” %1″);
commandKey.Close();
}
openKey.Close();
}
shellKey.Close();
}
schemeKey.Close();
}
hkcr.Close();
}
MessageBox.Show(string.Format(“Custom scheme {0}: installed.”, SchemeName.Text));
}
public MainWindow()
{
InitializeComponent();
var args = Environment.GetCommandLineArgs();
if (args.Length > 1)
{
Uri argUri;
if (Uri.TryCreate(args[1], UriKind.Absolute, out argUri))
{
var decoder = new WwwFormUrlDecoder(argUri.Query);
if (decoder.Any())
{
InputUrI.Text = string.Empty;
foreach (var entry in decoder)
{
InputUrI.Text += entry.Name + “=” + entry.Value + “,”;
inputs[entry.Name] = entry.Value;
}
InputUrI.Text = InputUrI.Text.Remove(InputUrI.Text.Length – 1);
}
}
}
}
The Windows10Launcher App
Now that we’ve built the WPF app we want to launch, lets take a quick look at the Universal Windows App that will be doing the launching. The Windows10Launcher app is exceedingly simple. It has a textbox where the URI we want to launch goes and a button that takes the text, converts it into a URI and launches it using our old friend Launcher.LaunchUriAsync. Here’s the click handler for the Launch WPF App button:
private async void LaunchWpfApp_Click(object sender, RoutedEventArgs e)
{
var launchUri = new Uri(UriToLaunch.Text);
await Launcher.LaunchUriAsync(launchUri);
}
One thought on “Launch a WPF (Win32) App from a Universal Windows App”