しばやん雑記

Azure Serverless とメイドさんが大好きなフリーランスのプログラマーのブログ

Windows App SDK 1.1 に移行したアプリを Microsoft Store で公開したらクラッシュが多発して困った話

以下のエントリで書いたように、UWP アプリを Windows App SDK 1.1 に移行したので Microsoft Store で公開したのですが、公開直後からクラッシュレポートが大量に発生してしまいました。

今は一通り対応が完了していて、大きな問題は発生していない状態なのですが、今回アプリを襲ったクラッシュ地獄について簡単にまとめたので、今後犠牲者が出ないように共有しておきます。

Windows 10 では使えない機能がある

Microsoft Store で Windows App SDK 版をリリースしたら、すぐにクラッシュが大量に発生していることがパートナーセンターから確認されました。起動時にクラッシュしていたのでかなり深刻でした。

アプリのウィンドウからアイコンを削除したかったので、IconShowOptions を使ってアイコンとシステムメニューを消す設定を追加したのですが、これが原因で Windows 10 で常に起動時にクラッシュしていました。

Windows App SDK は Windows 10 1809 以降に対応しているはずなので疑問に思っていたのですが、ドキュメントを確認すると TitleBar 周りのカスタマイズは Windows 11 限定となっていました。

Title bar customization APIs are currently supported on Windows 11 only. We recommend that you check AppWindowTitleBar.IsCustomizationSupported in your code before you call these APIs to ensure your app doesn't crash on other versions of Windows.

Title bar customization - Windows apps | Microsoft Docs

全て Windows 11 にアップグレード済みだったので、当然ながら手元では全く再現しませんでした。

ぶっちゃけ騙された気分ですし、Windows 11 でしか使えない API はコンパイル時に警告ぐらい出してほしいのですが、仕方ないので IsCustomizationSupported をチェックするコードを追加して対応しました。

if (AppWindowTitleBar.IsCustomizationSupported())
{
    appWindow.TitleBar.IconShowOptions = IconShowOptions.HideIconAndSystemMenu;
}

これが意味するのは、Windows 10 ではウィンドウからアイコンを削除する API が存在しないことです。

ドキュメントには Windows のバージョン間で一貫性があることを売りにしていますが、このように Feature Detection を書く必要があるのに一貫性があると言えるのか謎です。

後述する WebView2 でも思いましたが、基本的に新しく開発するアプリケーションは Windows 11 以降をターゲットにした方が良いと感じました。

アプリ内購入時に必ずクラッシュする

Windows 10 でのクラッシュは直りましたが、次はアプリ内購入で必ずクラッシュしていることが分かりました。マネタイズとして重要な要素となるので、ここでクラッシュするのは致命傷です。

Windows App SDK は実体が .NET 6 と WinRT Interop のキメラなので、ダイアログを表示する API は InitializeWithWindow を使って初期化する必要があるのですが、IAP に関しても同じ処理が必要でした。

ドキュメントにも記載があるのですが、Windows App Development 側にあったので気が付きませんでした。Desktop Bridge 向けなので .NET 6 という扱いですが、Windows App SDK でも基本は同じです。

ダイアログを表示するだけなのに、Windows App SDK は UWP のように簡単ではなく、Desktop Bridge と同じ追加コードが必要になるのが本当に納得出来ない部分です。もっと API を使いやすいようにラップしてくれという気持ちしか湧いてきません。

WebView2 ランタイムが存在しないケースがある

Windows App SDK では Chromium Edge ベースの WebView2 が標準で組み込まれているので、Web ページの表示は WebView2 を使う形になるのですが、WebView に比べると使い勝手が悪いです。

基本的な開発方法については公式ドキュメントを参照してください。表示だけなら簡単に使えます。

WebView2 は Chromium Edge ベースなので WebView よりも飛躍的に互換性が高まっているので便利ですが、WebView2 Runtime が別途必須になるのと初期化が非同期で行われるので実装で若干はまります。

特に開発初期には WebView2 クラスには大したメソッドやプロパティが無いことに気が付くはずです。まともなアプリを作るためには CoreWebView2 プロパティを直接触る必要が出てきますが、初期化が非同期で行われるので CoreWebView2 プロパティは null を返してくることがあります。

実際に操作を行う前に CoreWebView2 の初期化が終わっていないと面倒なので、明示的に初期化を実行するメソッドを呼び出します。これで CoreWebView2 の作成を強制できます。

これを使えば CoreWebView2not null として扱えるかと思いきや、WebView2 Runtime が存在しない場合を考慮する必要があるので null チェックは必要になります。

Windows 11 では WebView2 が Windows Update 経由で配布されているので気が付かないのですが、Windows 10 には存在しないケースがあるためチェックする必要があります。

await webView2.EnsureCoreWebView2Async();

if (webView2.CoreWebView2 is null)
{
    // WebView2 Runtime がインストールされていないとして扱う
}

初期化後に呼び出されるイベントもあるので、コンストラクタ内など await 出来ない場面で使えます。

WebView2 がインストールされていない場合などで初期化に失敗した時には、イベントの情報として例外が渡されるので成功したかどうかが判定できます。

最近になって Windows 10 にも WebView2 Runtime の配布が始まったようなので、今後は WebView2 Runtime は存在する前提で良くなりそうなのが救いです。

Microsoft の対応を見ていてわかるように Windows 11 への対応が優先されるようなので、Windows 10 のサポートを早々に切りたくなる理由がまた一つ増えました。

App Center Analytics が動作しない

最後はサービス自体の継続性が若干怪しい App Center ですが、最新版の SDK をインストールしても Analytics のデータが確認出来なくなりました。

App Cener SDK のログを出力させるとテレメトリ自体は送信成功していますが、何故か App Center から確認出来ないという謎の状況が発生しています。GitHub の Issue も上がっていますがあまり進展はないです。

Analytics の確認は出来ないですが、何故か Crashes は確認出来ているのでエラーの特定は可能です。実際に TitleBar や WebView2 のエラーの解決には役に立ってくれました。