Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Windows toast notifications without a COM server

0.00/5 (No votes)
14 May 2017 1  
An easy way to react on windows toasts activation without using a COM server

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:
 
C#
private void RegisterProtocol(string exePath)
{
    // to register this url protocol for all users use LocalMachine instead and elevation of admin rights will be required
    RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Clases\\" + urlProtocol);//open myApp protocol's subkey

    if (key == null)  //if the protocol is not registered yet...we register it
    {
        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");
        //%1 represents the argument - this tells windows to open this program with an argument / parameter
    }
    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).

XML
<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.

C#
// Create the toast and attach event listeners
   ToastNotification toast = new ToastNotification(dom);
   toast.Activated += Toast_Activated;

// Show the toast. Be sure to specify the AppUserModelId on your application's shortcut!
   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.

C#
public MainWindow()
{
    bool createdNew;

    // we want to prevent starting a new instance of the application through url protocol launch when our toast is activated and our application is already running
    _mutex = new Mutex(true, AppName, out createdNew);

    if (!createdNew)
    {
        //app is already running! Exiting the application 
        Application.Current.Shutdown();
    }
    else
    {
        InitializeComponent();
        // other stuff
    }
}

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here