Windows 8でトースト通知を行ってみる

2013.09.02

Windowsデスクトップアプリからのトースト通知

最近AWSに関する通知の事を考えることがあります。障害の通知といえば、メールによる通知、電話による通知などがよく用いられています。

そこで、ふとPCのデスクトップに障害通知を行ってみてはと思い、Windowsデスクトップ向けのトースト通知のサンプルアプリケーションを動かしてみました。

Windows 8でのトースト通知(デスクトップ通知)は下記のようなものになります:

Windows Toast Notification 01

デスクトップトースト通知サンプル

まず、下記からサンプルアプリケーションをダウンロードします。

C++版とC#版のサンプルがダウンロードできます。本記事ではC#版をダウンロードしています。

サンプルをダウロードしたら、プロジェクトフォルダを適当な場所に移動し、ToastNotificationSampleという名前にリネームしておきます。

Windows® API Code Pack for Microsoft® .NET Framework

このサンプルを実行するにはWindows® API Code Pack for Microsoft® .NET Frameworkが必要になります。

上記サイトからライブラリをダウンロードすることもできるのですが、NuGetでインストールすると楽ですので、今回はNuGetでインストールを行っておきます。

ダウンロードしたサンプルプロジェクトを開き、参照設定のNuGetパッケージの管理で下記をインストールしておきます:

  • Windows 7 API Code Pack
  • Windows 7 API Code Pack - Core
  • Windows 7 API Code Pack - Shell

アプリケーションの画面構成

サンプルアプリケーションはWPFアプリケーションとなっています。まずは画面のコードを見て行きたいですが、画面のコードは非常に簡単なものとなっています。

画面のイメージは下記のようになります。

Windows Toast Notification 02

MainWindow.xamlのソースコードは下記のような非常にシンプルなものです。

<Window x:Class="DesktopToastsSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Desktop Toasts Sample" Height="200" Width="300">
    <StackPanel Orientation="Vertical">
        <Button x:Name="ShowToastButton" Height="50">Show Toast</Button>
        <TextBlock x:Name="Output" Margin="10" TextWrapping="Wrap">Whatever action you take on the displayed toast will appear here</TextBlock>
    </StackPanel>
</Window>

スタートメニューショートカット作成処理

デスクトップアプリケーションがトーストを表示するためには、スタートメニューにショートカットを持っている必要があります。また、AppUserModelIDがそのショートカットに設定されている必要があります。この要件を実現するコードで、先ほど準備したWindows® API Code Pack for Microsoft® .NET Frameworkが必要になります。

スタートメニューショートカットの作成処理は下記のようになります:

private bool TryCreateShortcut()
        {
            String shortcutPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Microsoft\\Windows\\Start Menu\\Programs\\Desktop Toasts Sample CS.lnk";
            if (!File.Exists(shortcutPath))
            {
                InstallShortcut(shortcutPath);
                return true;
            }
            return false;
        }

        private void InstallShortcut(String shortcutPath)
        {
            String exePath = Process.GetCurrentProcess().MainModule.FileName;
            IShellLinkW newShortcut = (IShellLinkW)new CShellLink();

            ShellHelpers.ErrorHelper.VerifySucceeded(newShortcut.SetPath(exePath));
            ShellHelpers.ErrorHelper.VerifySucceeded(newShortcut.SetArguments(""));

            IPropertyStore newShortcutProperties = (IPropertyStore)newShortcut;

            using (PropVariant appId = new PropVariant(APP_ID))
            {
                ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutProperties.SetValue(SystemProperties.System.AppUserModel.ID, appId));
                ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutProperties.Commit());
            }

            IPersistFile newShortcutSave = (IPersistFile)newShortcut;

            ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutSave.Save(shortcutPath, true));
        }

トースト通知処理

次に、トースト通知処理は下記のような処理の流れになります。

  • トースト通知用のXMLを作成する
  • 上記XMLを元にToastNotificationオブジェクトを作成する
  • トーストの表示、消失時のイベントをToastNotificationオブジェクトに設定する
  • ToastNotificationManagerを用いてトースト通知を実行する

実際の処理は下記のようになります:

private void ShowToastButton_Click(object sender, RoutedEventArgs e) { XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04);

XmlNodeList stringElements = toastXml.GetElementsByTagName("text"); for (int i = 0; i < stringElements.Length; i++) { stringElements[i].AppendChild(toastXml.CreateTextNode("Line " + i)); } String imagePath = "file:///" + Path.GetFullPath("toastImageAndText.png"); XmlNodeList imageElements = toastXml.GetElementsByTagName("image"); imageElements[0].Attributes.GetNamedItem("src").NodeValue = imagePath; ToastNotification toast = new ToastNotification(toastXml); toast.Activated += ToastActivated; toast.Dismissed += ToastDismissed; toast.Failed += ToastFailed; ToastNotificationManager.CreateToastNotifier(APP_ID).Show(toast); } [/csharp]

最後に

デスクトップアプリケーションからトースト通知ができるようになりました。これでサーバーで障害が発生した際に、デスクトップに通知を行ったり出来そうになりましたw

サンプルでは通知を起動させるアプリケーションが表示されていましたが、実際には画面が無い常駐アプリケーションからトースト通知を行いたいところです。これに関しては引き続き調査していきたいと思っています。

参考