Introduction
Starting with Windows 8.0, Microsoft added a concept of toast notifications. In compare to older balloon notifications, toast notifications may residue in the action center after they disappear from your screen. This allows your applications to persist notifications for a longer time span (up to 3 days) and let your user react on it later.
Background
As this quick guide by Microsoft (https://blogs.msdn.microsoft.com/tiles_and_toasts/2015/10/16/quickstart-handling-toast-activations-from-win32-apps-in-windows-10/) states, if you want to react on a toast activation once your application is not running anymore, a COM server is required to activate your application. Doing this, you need to write not very C#-friendly code. If you are not a fan of such approach, there is another, much easier and surprisingly not mentioned anywhere, way how to “wake up” your application when a toast is activated.
Asynchronous Pluggable Protocols to rescue
Windows allows to launch your application by using something called URL protocol. You already know some such as http: or ftp:. If you use
Process.Start
(
http://www.google.com), first part of that string (http😊 is recognized as a URL protocol which is associated with some specific application. There are several protocols already predefined but you can easily add your own and associate it with your application as described here:
https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
It is as simple as:
private void RegisterProtocol(string exePath)
{
RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Clases\\" + urlProtocol);
if (key == null)
{
key = Registry.CurrentUser.CreateSubKey("Software\\Classes\\" + urlProtocol);
key.SetValue(string.Empty, "URL: " + urlProtocol);
key.SetValue("URL Protocol", string.Empty);
key = key.CreateSubKey(@"shell\open\command");
key.SetValue(string.Empty, exePath + " " + "%1");
}
key.Close();
}
Why is this interesting to us?
If you look at the XML to define toast notifications you can notice a parameter called “activationType” and the value “protocol” is particularly interesting to us. If you use this value you need to specify string to be used to launch this URL protocol. For that purpose, we use attribute “launch” (or in “arguments” if you are using it inside actions).
<toast launch="my-cool-app:arguments_for_my_app" activationType="protocol">
<visual>
<binding template="ToastGeneric">
<text>My test app using protocol</text>
</binding>
</visual>
</toast>
Using the code
Toast definition above will cause, that every time a user clicks on a notification, Windows will try to start your application with the arguments you provided for the toast (this is different in compare to a COM activation approach when we let Windows know that our application is running). However, we don’t want to start our application again when it is already running as we have events which reacts on toast actions.
ToastNotification toast = new ToastNotification(dom);
toast.Activated += Toast_Activated;
ToastNotificationManager.CreateToastNotifier(myAppID).Show(toast);
To ensure that the toast will not start our application again, we need to implement a mutex to keep only one instance of our application running. If Windows try to start a new instance of our application we will simply close it before we initialize anything and ignore it.
public MainWindow()
{
bool createdNew;
_mutex = new Mutex(true, AppName, out createdNew);
if (!createdNew)
{
Application.Current.Shutdown();
}
else
{
InitializeComponent();
}
}
Points of Interest
This is all you need to react on toasts activations. Check out the full sample provided. The sample also includes a registration of a shortcut in the start menu as it is required to keep notifications in the action center – they would disappear otherwise.
History
This is the first version.