Windowsで通知用アプリを作ろうとした時に悩んだ諸々

### 作った通知用アプリについて
- C#を使用する
- トースト通知（Toast Notification、右下に出てくる短冊状のアレ）で何かを知らせる
- TCPソケットで通知内容を受信する
- システムトレイ（System Tray）＝タスクトレイ（Task Tray）にアイコンを出し、メニューから終了できる

### WPFとUWPって何？
- [Windows 10 アプリを作ってみる【説明編】【UWPとは？】【他のWindowsアプリとの違い】 – ちょ窓帳](https://blogs.msdn.microsoft.com/chomado/uwp/what-is-uwp/)
- [Step up WPF - Speaker Deck](https://speakerdeck.com/grabacr07/step-up-wpf)

**結論**

- WPF：Windowsのデスクトップアプリを作る時に使用するフレームワーク
- UWP：Windows（Phoneとかも含めた）全般でアプリを動作させるプラットフォーム
- Win10のデスクトップ用アプリwithシステムトレイはWPFが楽
    - [UWP app with Systray extension – Insights into the Universal Windows Platform](https://stefanwick.com/2017/06/24/uwp-app-with-systray-extension/)
    - これから分かるようにUWPからでも可能だが面倒（に感じた）

### WPFでどうすればタスクトレイにアイコンを出せるの？

- [C# WPF で タスクトレイ 常駐アプリ の 開発 - galife](https://garafu.blogspot.com/2015/06/dev-tasktray-residentapplication.html)
- [Windowsタスクトレイ常駐型のアプリを作る（WPF版） - ふるすたっくえんじにあの日記](http://devdevdev.hatenablog.com/entry/2018/05/02/215133)

**結論**

- Visual Studioでちゃちゃっと出来る

### 終了機能を作る前に実行しちまった！どうやって消すんだ…

**結論**

- **タスクマネージャー**で消せる
- Visual Studioから起動したなら、VS下にあります
    - ![test3.png](https://qiita-image-store.s3.amazonaws.com/0/186959/e3643869-65f7-d20f-64bf-c774ad1f2270.png)
- 普通に起動してもバックグラウンドプロセス下にあります
    - 分かりやすい名前を付けておくと◯


### Threadが古い！？Taskって何だよ！

**結論**

- 分からねえ・・
- Taskを使ったTCP接続のサンプル → [C#でTCP接続テスト / fujimisakari blog](http://blog.fujimisakari.com/tcp_connection_test_on_c_sharp/)

### TCP通信が外部PCと繋がらん

- [Windows10で特定のポートを開放する – Born Digital サポート](https://support.borndigital.co.jp/hc/ja/articles/360002711593-Windows10%E3%81%A7%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%9D%E3%83%BC%E3%83%88%E3%82%92%E9%96%8B%E6%94%BE%E3%81%99%E3%82%8B)
- [Windowsファイアウォールの例外にアプリケーションを追加する方法 | バッファロー](https://www.buffalo.jp/support/faq/detail/792.html)

**結論**

- ファイアウォールでポートを解放
- `Windows Defender ファイアウォールを介したアプリまたは機能を許可`で作成したEXEファイルを登録
    - EXEファイルを初めて起動した時にOSが聞いてくれるはず

### ToastNotificationManager.CreateToastNotifier(applicationId)のapplicationIdとは

- [ToastNotificationManager.CreateToastNotifier Method (Windows.UI.Notifications) - Windows UWP applications | Microsoft Docs](https://docs.microsoft.com/en-us/uwp/api/windows.ui.notifications.toastnotificationmanager.createtoastnotifier)
- [Application User Model IDs (AppUserModelIDs) - Windows applications | Microsoft Docs](https://docs.microsoft.com/en-us/windows/desktop/shell/appids)

**結論**

- __Application User Model IDs (AppUserModelIDs)__
- このメソッドを使うときには必須
    - 昔はなくてもトースト通知を発生させられた
    - 自分のアプリのIDは設定しないと存在しないが、他のアプリのを流用可能
    - ゴミ箱 `"::{645FF040-5081-101B-9F08-00AA002F954E}"`でやるとこんな感じに
        - ![test2.png](https://qiita-image-store.s3.amazonaws.com/0/186959/9cdc983e-1ab7-d264-6389-570d9bd97df3.png)
        - ![test.png](https://qiita-image-store.s3.amazonaws.com/0/186959/359f556b-b47b-5541-7717-eae9dcf3a98e.png)
- 登録済みのID一覧は手軽に取得できる
    - [AppUserModelId(AUMID)を列挙するVBScript | 初心者備忘録](https://www.ka-net.org/blog/?p=6250)

:::note warn
2025/01/21追記
Windown 11 に上げた影響か `"::{645FF040-5081-101B-9F08-00AA002F954E}"` では通知が発生しなくなった。 `"{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe"` が代替候補の一つ。

:::



### 通知よ、ユーザーが反応するまで消えてくれるな

- [トーストのコンテンツ - UWP app developer | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts#alarms-reminders-and-incoming-calls)

**結論**

- toastのscenarioを`reminder`に設定すればOK
- マウスでトーストをクリックするまで残り続けるようになる
- 以下は2種類の作り方での例

```c#
ToastContent content = new ToastContent()
{
    Scenario = ToastScenario.Reminder,
    //（略）
}
```

```xml
<toast scenario="reminder" launch="app-defined-string">
    <!--（略）-->
</toast>
```


### 出ない通知

- エラーログを送りつけたら、通知が発生しない

```:ASCII文字のみの場合
Unhandled Exception: System.Exception: 通知の内容のサイズが大きすぎます。

通知の内容のサイズが大きすぎます。

   at Windows.UI.Notifications.ToastNotifier.Show(ToastNotification notification)
   at ToastTest.NotifyToaster.Fire(String msg)
```

```:マルチバイト文字混じりの場合
Unhandled Exception: System.ArgumentException: Value does not fall within the expected range.
   at Windows.UI.Notifications.ToastNotifier.Show(ToastNotification notification)
   at ToastTest.NotifyToaster.Fire(String msg)
```

**結論**

- [Notification Window font size is suddenly huge - Malwarebytes 3 Support Forum - Malwarebytes Forums](https://forums.malwarebytes.com/topic/234949-notification-window-font-size-is-suddenly-huge/)
- 通知内の文字バイト数はざっくり4000以下に収めよう！
- そもそも、通知領域的に( `,` や `.` で)600字が限度
    - 横長文字ならもっと少ない