.NET 9 の .NET MAUI(WinUI)で BackgroundTaskRegistration.AllTasks が COMException(-2147023728 / 0x80070490)になる原因と回避策

Windows 10 + Visual Studio 2022 環境で .NET 9 の .NET MAUI(Windows/WinUI)アプリを作り、BackgroundTaskRegistration.AllTasks.Count を参照しただけで COMException(-2147023728 / 0x80070490)で落ちる――そんな現象の原因切り分けと回避策をまとめます。

目次

現象:AllTasks を触った瞬間に COMException でクラッシュする

対象は「バックグラウンドタスクを登録する前の段階」です。つまり、.winmd の生成やマニフェスト拡張、登録処理(BackgroundTaskBuilder / BackgroundExecutionManager など)に進む以前に、列挙用のプロパティに触れただけで例外が発生します。ここがこの問題をやっかいにしています。

項目内容(例)
OSWindows 10(build 19045 系)
IDEVisual Studio 2022
プロジェクト.NET MAUI(単一/複数プロジェクトどちらでも再現)
ターゲット.NET 9(Windows/WinUI)
トリガーBackgroundTaskRegistration.AllTasks.Count を読むだけ
例外System.Runtime.InteropServices.COMException(HResult: 0x80070490

GitHub の .NET MAUI リポジトリでも、「新規 .NET 9 MAUI プロジェクト + 1行追加」で再現する報告が上がっており、再現手順とスタックトレースが共有されています。

最小再現:新規 MAUI プロジェクトに 1 行足すだけ

MAUI の Windows 側(例:Platforms/Windows/App.xaml.cs)に、次の 1 行を追加します。ポイントは「登録処理は何もしていない」「AllTasks の Count を読むだけ」です。

using Windows.ApplicationModel.Background;

public partial class App : MauiWinUIApplication
{
    public App()
    {
        InitializeComponent();

        // ★この 1 行だけで COMException(0x80070490)が発生するケースがある
        System.Diagnostics.Debug.WriteLine(BackgroundTaskRegistration.AllTasks.Count);
    }
}

実際の報告では、.NET 8 では動作する一方、.NET 9 で同じコードが COMException -2147023728(0x80070490) を投げる、という「回帰(regression)」として扱われています。

エラーコード -2147023728 の正体:0x80070490(Element not found)

-2147023728 を 16 進数にすると 0x80070490 です。これは Win32 的には「Element not found」に相当する HRESULT で、WinRT 呼び出しの結果として WinRT.Runtime 側で COMException に変換されます。実際に報告のスタックトレースでも、BackgroundTaskRegistration.get_AllTasks() を呼び出したところで HResult=0x80070490 が返ってきています。

通常、BackgroundTaskRegistration.AllTasks は「アプリが登録済みのバックグラウンドタスク」を列挙するためのプロパティです。タスクが 0 件なら空のコレクションが返り、そこから Count を読める、というのが素直な期待値です。

なぜ「登録前」なのに落ちるのか:実装ミスより“土台”の問題を疑う

この現象の重要なポイントは、実装手順(.winmd、マニフェスト、登録コード)を間違えたから落ちている、というより、WinRT へのブリッジ(CsWinRT/WinRT.Runtime)や Windows 側の背景タスク基盤に触れた瞬間に例外になる点です。

実際、Microsoft Q&A 側でも「.NET 8 では動くが .NET 9 では動かない」という切り分けが提示され、当面の回避として .NET 8 を使う案が採られています(同時にバグ報告は GitHub へ、という案内)。

さらに、Windows App SDK(WinUI 3)側でも似た形で BackgroundTaskRegistration のメンバー参照が 0x80070490 を返す報告が過去にあり、必ずしも「呼び出し側のコードだけ」の問題とは限らないことが分かります。

WPF(C#/WinRT サンプル)では動くのに、MAUI では進めないのはなぜ?

「同じ C#/WinRT の方向性で、WPF では背景タスクが動くのに MAUI だと最初の AllTasks 参照で落ちる」という話は、現場でも混乱しやすいポイントです。ここは“アプリの種類”というより “実行形態と土台の違い”として捉えると整理しやすくなります。

  • WPF 側のサンプルは、背景タスク基盤が動く前提(MSIX でのパッケージ化、マニフェスト、エントリポイント)を満たしているケースが多い
  • MAUI(WinUI 3)側は、内部的に Windows App SDK と CsWinRT を介して WinRT API を呼ぶため、SDK バージョン差や初期化の差が直撃しやすい
  • 今回の症状は「登録手順に入る前に落ちる」ので、アプリ側の .winmd/マニフェストのミスというよりフレームワーク/SDK 側の回帰や相性として切り分けやすい

開発の現実解としては、背景タスク周りを深掘りする前に、まず .NET 8 で土台を安定させるのが安全です。土台が安定してから、WinUI 3 / Windows App SDK の流儀に寄せる(あるいは Windows 専用実装として切り出す)方が、結果的に手戻りが少なくなります。

まずやるべき切り分けチェック

「.NET 9 の回帰っぽい」場合でも、再現条件を狭めると回避策や別ルートが見つかることがあります。特に Windows のバックグラウンドタスクは、アプリの実行形態(パッケージ有無)呼び出しタイミングで挙動が変わりやすい領域です。

観点確認方法狙い
HResult が同じか例外の HResult を確認(-2147023728 / 0x80070490)同一事象として扱えるかを判定
呼び出し場所WinUI 側の App コンストラクタ以外(例:起動後イベント)でも試す初期化タイミング依存の可能性を排除
パッケージ IDMSIX でインストールされているか、起動構成が意図通りかを確認「パッケージ前提 API」を使っていないか確認
.NET 8 で再現するか同じソースで net8.0-windows に落として実行回帰かどうかを最短で見極める

この問題は「.NET 8 では動くが .NET 9 では落ちる」という切り分けが非常に強力です。もし .NET 8 で例外が消えるなら、アプリ固有のロジックよりも、フレームワーク/SDK 側の挙動差として考えるのが合理的です。

結論:現実的な回避策は .NET 8 で進める

現時点で最も再現性が高く、しかも実務的に効く回避策は、Windows を含めて .NET 8 ターゲットで MAUI を構築することです。すでに複数の報告で「.NET 8 では動く」ことが確認されており、当面の進め方として合理的です。

.NET 9 → .NET 8 に落とす例(csproj)

プロジェクトの .csprojTargetFrameworks を .NET 8 系に変更します(Windows の TFMs も net8.0-windows... に)。

<PropertyGroup>
  <TargetFrameworks>
    net8.0-android;
    net8.0-ios;
    net8.0-maccatalyst;
    net8.0-windows10.0.19041.0
  </TargetFrameworks>
  <UseMaui>true</UseMaui>
</PropertyGroup>

Visual Studio のワークロードや SDK の揃い方によっては、.NET 8/9 の切り替え時に関連コンポーネントの追加インストールが走ることがあります。チーム開発では、ビルド環境の差によって再現/非再現が分かれることもあるため、CI も含めてターゲットを統一しておくと安全です。

「どうしても .NET 9 を使いたい」場合にできること

現実には、別要件(他プラットフォームの都合やパッケージ互換性)で .NET 9 を維持したいケースもあります。ただし今回の症状は「AllTasks 参照が通らない」ため、バックグラウンドタスク関連の実装を進めるのが難しい状態です。ここでは “落としどころ” をいくつか提示します。

アプリを落とさない(try/catch で防御)

まずはクラッシュ回避です。根治ではありませんが、例外を握って起動は継続できるようにします。バックグラウンドタスクが必須でない画面や機能から順に作り込む場合、開発効率が上がります。

using System.Runtime.InteropServices;
using Windows.ApplicationModel.Background;

int taskCount = 0;

try
{
    taskCount = BackgroundTaskRegistration.AllTasks.Count;
}
catch (COMException ex) when ((uint)ex.HResult == 0x80070490)
{
    // .NET 9 + MAUI で発生しうる例外パターン(Element not found)
    // ここでは「未取得扱い」にして処理を継続
    taskCount = -1;
}

注意:例外を握るのは「落ちないようにする」だけで、背景タスクの列挙・登録が可能になるわけではありません。後述の回避策(.NET 8)または別アーキテクチャへの切り替えを前提にしてください。

WinUI 3 / Windows App SDK の「背景タスク」アプローチを検討する

MAUI の Windows 実装は WinUI 3(Windows App SDK)ベースです。Microsoft Learn の背景タスク解説では、従来の WinRT(UWP)向け BackgroundTaskBuilder はデスクトップ(フルトラスト)では制約があり、Windows App SDK 側の API がその回避を提供する、という整理がされています。

つまり「UWP の作法(Windows.ApplicationModel.Background)をそのまま MAUI/WinUI 3 に持ち込む」よりも、Windows App SDK の前提に寄せた設計の方が、長期的にはハマりどころが減ります。今回の現象が .NET 9 の回帰であったとしても、将来的に別の箇所で同種の壁に当たる可能性があるため、早い段階で設計方針を決めておくのがおすすめです。

“回帰(regression)” としての状況:既に報告は存在する

本件は「自分だけの環境問題」ではなく、.NET MAUI 側で再現報告があり、regressed-in-9.0.0 のラベル付きで扱われています。一方で issue は “not planned” としてクローズされているため、短期での修正を前提に計画を組むのは危険です。

この手の「プラットフォーム境界の不具合」は、アプリ側で回避しきれないことも多いです。だからこそ、プロジェクト管理の観点では次の二段構えが現実的です。

  • 実装は .NET 8 で進めて成果を積む(AllTasks を含む API が動作する環境で開発・検証を回す)
  • .NET 9 の継続調査は別レーン(サービスリリースや関連 issue の動向を追う)

バグ報告・調査を加速するためのメモ(そのまま貼れる情報)

もし社内ルール的に .NET 9 固定で進める必要がある場合、調査コストを下げるには「報告の質」を上げるのが近道です。GitHub issue や VS Feedback に投げる際は、最低限次の情報があると話が早いです。

項目
OSWindows 10 build 19045.x(例:19045.5371)
MAUI / SDKMAUI 9.x(例:9.0.14 SR1.4)
再現手順新規 MAUI プロジェクト + App コンストラクタに 1 行追加
例外COMException -2147023728(0x80070490)
比較.NET 8 では動作、.NET 9 で落ちる

ここまで揃っていると、少なくとも「再現しないので終わり」になりにくく、担当者が環境を合わせて追いやすくなります。

よくある質問

AllTasks は “登録済みタスクが無いと落ちる” API なの?

一般的にはその認識は誤りです。BackgroundTaskRegistration.AllTasks は「登録済みタスクの列挙」であり、未登録なら空のコレクションになるのが自然です(少なくとも API の意図としてはそう扱えるように設計されています)。

MAUI だと Windows のバックグラウンドタスクはそもそも無理?

目的によります。Windows の「バックグラウンドで動く仕組み」は複数あり、UWP 互換の background task、Windows App SDK の background task、通知(プッシュ/ローカル)、タスクスケジューラ、常駐プロセス(サービス)など選択肢が分かれます。MAUI は UI フレームワークなので「OS の常駐・トリガー実行」をどこまで担うかは別設計になることが多いです。

今回のように “AllTasks を読むだけで落ちる” 状況では、背景タスクの方式を MAUI 内に抱え込むより、Windows 側だけ別プロジェクト(WinUI 3 / Win32)で責務分離する、といった判断が結果的に安全になることがあります。

今後 .NET 9 で直る可能性は?

可能性はありますが、現時点では「直る前提」で進めるのはおすすめしません。既に再現報告はありつつも、クローズ(not planned)になっているため、修正の優先順位が高いとは言い切れないためです。

まとめ:このケースは “手順の前に落ちる” ので、まず土台を戻す

バックグラウンドタスクは、実装手順そのものも複雑ですが、今回のポイントはそこではありません。AllTasks 参照だけで COMException(0x80070490)が出る以上、手順を積み上げても前に進みにくい状態です。

そのため、現実的には次の判断が最短距離になります。

  • 当面は .NET 8 で MAUI(Windows/WinUI)実装を進める
  • .NET 9 は不具合として追跡・報告し、状況が動いたら戻す

「原因究明」に時間を溶かすより、動く土台に戻して機能開発を進め、並行して issue を追う――この二段構えが、いちばん損をしにくい進め方です。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次