The previous post presented how file association is used to exchange information between Windows Store Apps (WSAs) and Desktop Apps (DAs). The same kind of feature can be provided by the protocol association.
WARNING: all these techniques are violating the point 3.1 from the Windows Store Requirements that states: “Your app may only depend on software listed in the Windows Store“. Therefore, you should not use them for a WSA that you plan to publish into the Windows Store because it will be rejected.
How to activate another application?
From a WSA, the Launcher.LaunchUriAsync
method activates another application that is associated to a given protocol.
The LauncherOptions
is set to avoid unnecessary popup to the end user.
LauncherOptions options = new LauncherOptions();
options.DisplayApplicationPicker = false;
options.TreatAsUntrusted = false;
// See Mainform.cs for the details of the daipp protocol syntax
Uri uri = new Uri("daipp://...");
bool success = await Launcher.LaunchUriAsync(uri, options);
The uri format must follow the usual url rules or you’ll get a System.UriFormatException
with “Invalid URI: The hostname could not be parsed” as a reason. For example
will fail because there is no initial host name.
I’m using the command to be parsed by the activated application as the hostname:
The parameters are then passed as value pairs with the same format as a query string. Spaces are supported but values and parameter names should not contain the ‘=’ character.
In the DA case, the Process.Start method activates the associated application:
Process p = Process.Start(string.Format("saipp://{0}", answer));
Unfortunately, the returned Process
instance is always null… Does it means that it is impossible to figure out if something went wrong? Not always. You know when the WSA associated with the protocol does not start fast enough because a Win32Exception
is thrown by Process.Start
.
For other weird errors such as crashes in the activated WSA, another WinException
will be thrown but this time with a remote procedure call failure.
If you want to test a protocol, simply use the Run dialog box that pops up when you hit WIN+R.
When you type the bingweather protocol, guess what? The Windows Weather WSA will be activated! This is the basics to build shortcuts to well-known installed Windows WSA and read this post for more détails.
How to associate an application to a custom protocol?
As with file extension, a WSA registers a protocol in its manifest via the Déclarations section
Without any surprise, a DA registers a custom protocol in the Registry under HKEY_CLASSES_ROOT and the protocol name
The default value of the “command” subkey points to the command line to execute.
How to handle application activation?
When a WSA gets activated, the OnActivated
override of its Application
-derived class is called. The received IActivatedEventArgs
parameter provides an ActivationKind
information via the Kind
property with Protocol
as value. In that particular case, the argument should be cast into ProtocolActivatedEventArgs
to access the expected Uri
This Uri
type comes from WinRT, not from the BCL.
The WIN+R Run dialog box helps you to test your uri values
In that case, the received Uri looks like the following under the debugger:
The Host
and LocaPath
properties are your friends because they have been url-decoded, unlike the AbsolutePath
and AbsoluteUri
properties. There is a gotcha if the uri is not well-formed: when you try to access the Uri
property of the activation argument override, a System.UriFormatException
is raised without any chance to get access to the original string uri. Even worse, as explained in MSDN, this exception is not available for WSA. As a consequence, you need to catch the base class FormatException
to detect such a case.
For a DA, the uri is passed via the command line
without any need to uri-decode the string. The Environment.CommandLine
property starts with the process pathname surrounded by quotes followed by a space and the protocol query string.
Use a query string Luke!
The two commands the DA provides via the custom protocol will start a DA like Notepad.exe or activate a WSA. As the previous examples have shown, the best way to define you’re a protocol is to use a query string-based syntax. Unlike Bing Map, it won’t be too complicated because only a few parameters are needed.
Activate a WSA from a DA
This code is first checking if the given WSA identity is installed on the machine by leveraging the PackageManager type exposed by WinRT. This code has already been detailed in one of my posts where I described how to call WinRT API from a DA.
The WinRT API can’t help for the activation part but, hopefully, the Windows SDK exposes in ShObjIdl.h the signatures and GUID necessary to activate a WSA as described in http://msdn.microsoft.com/en-us/library/windows/desktop/hh706902(v=vs.85).aspx.
The complicated part is to build the first parameter of the ApplicationActivationManager.ActivateApplication
method. We are lucky that the Package
returned by the WinRT PackageManager
provides exactly what we need as shown in the following code:
Start a DA from a DA
This one is very easy to implement thanks to the Process.Start
method method that accepts the executable as a parameter.
Download source code for WSA and DA
The next and last post of the series will discuss advanced communication scenario such as silent communication, without switching the user between the Modern UI world and the Desktop world.
Pingback: Windows Store Developer Links – 2013-04-16 | Dan Rigby
Great article! But I have a little problem… everything worked as expected for untill today… the WSA fires the launchUriAsync but the DSA does not catches that event… everything in my registry is as expected, did not change anything… do you anything about that kind of behavior all of the sudden?
Regards
Hi Sebastian,
I don’t have an immediate explanation for this king of magical change: usually something has been updated to trigger this behavior modification. The DSA should be started by Windows: did you try the url via the Run dialog?
What you can do is to check in the Control Panel (see the détails in the previous post) if the protocol is still well defined. You could also remove the definition by hand in the Registry (sorry but I did not think about providing the code for that cleanup) and redo the registration as an Admin. It is also possible that another App has been registered to the same protocol: you should detect it in the Control Panel.
Are you using my sample or have you built your own version?
I hope this helps.
Thanks Christophe, I got it running again by exporting the registry, deleting the entry to my protocol and adding it back again 😦
I have no idea what happened but it is now working again! Thanks
Magic…
Pingback: Inter-Process Silent Communication in WinRT – Part 4 | Anything about WinRT