1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WinUI 3 + .NET 9 で個人開発:Native AOTの地獄を乗り越え、難読化で妥協点を見出すまでの全記録

1
Last updated at Posted at 2026-05-19

はじめに

LINEのリッチメニューを管理するデスクトップアプリ「LichMenuLab」を開発する中で、知的財産(ライセンス判定ロジック等)の保護と、配布サイズの軽量化を目指して Native AOT に挑戦しました。
しかし、そこにはWinUI 3特有の深い闇が待っていました。本記事では、AOT断念の理由と、代替案としての難読化(Obfuscar)で直面した技術的トラブル、その解決策について共有します。


1. Native AOT への挑戦と、絶望の理由

当初、起動速度の向上とバイナリ解析防止のために .NET 9 の Native AOT を採用しようとしました。しかし、以下の理由により断念せざるを得ませんでした。

① ComboBox とデータバインディングの相性の悪さ

WinUI 3のバインディング({x:Bind})はコンパイル時にチェックされますが、データテンプレート内の型解決が Native AOT のトリミングによって実行時に失敗するケースが多発しました。特に ComboBoxSelectedItem 周りで型が欠落し、アプリが理由もなくアサートする現象に悩まされました。

② リフレクションの壁

多くのライブラリ(CommunityToolkit.Mvvm 等)が内部でリフレクションを使用しており、DynamicDependency をコード中に書きまくる作業が発生しました。「どこが消されたのか」を探すデバッグは、まさに「砂漠で針を探す」ような苦行でした。

③ 圧倒的な情報の少なさ

Microsoftの公式ドキュメントですら、WinUI 3 + Native AOT は「実験的」なニュアンスが強く、スタック・オーバーフローにも解決策が落ちていない。エンジニアとしての直感が「これはまだ本番で使うべきではない」と告げました。


2. 次の策:難読化(Obfuscar)への舵切り

Native AOT を諦め、従来の JIT コンパイルを維持しつつ、ロジックを隠蔽するために Obfuscar(オープンソースの難読化ツール)を導入しました。しかし、ここで新たな強敵が現れます。

直面したエラー:0xC000027B (アプリケーション内部例外)

難読化してビルドした瞬間、アプリが起動すらしない。ログも出ない。
ILSpyでバイナリを覗くと、原因は 「名前空間とクラスのリネーム」 にありました。


3. 難読化 vs JSONソースジェネレーターの競合

.NET 8 以降、難読化と相性の悪いのが JSON Source Generation (System.Text.Json) です。

失敗のメカニズム

  1. 難読化ツールがクラス名を A.a に変える
  2. ソースジェネレーターが生成したシリアライズ用コードは、元の名前 MyDataModel を探そうとする
  3. リフレクションとトリミングの競合により、デシリアライズ時に「コンストラクタの引数名がnullである」といったエラーを吐いて沈む

解決策:ロジックの完全分離(CoreLogicパターン)

UIに関わるプロパティ(ViewModel等)は難読化をスキップし、「純粋なアルゴリズム」と「秘匿文字列」だけを internal な別クラスに切り出し、そこだけを狙い撃ちで難読化する手法を採りました。

obfuscar.xml
<!-- UIやバインディングに関わる名前空間は死守する -->
<SkipNamespace name="LichMenuLab.ViewModels" />
<SkipNamespace name="LichMenuLab.Models" />

<!-- 核心ロジックが含まれるサービス層だけを難読化の対象とする -->
<Type name="LichMenuLab.Services.InternalCoreLogic" PreserveMethods="false" />

4. 教訓:WinUI 3開発における「現実的な」IP保護

今回の開発で得た知見は以下の通りです。

  1. Native AOT は時期尚早: WinUI 3 などのUIフレームワークと Native AOT の完全な調和には、まだ数年かかる?(苦行の好きな勇者が沢山現れるのを待つ)
  2. バインディング命: WinUI 3 はリフレクションへの依存度が低そうに見えて、内部的には名前(文字列)での紐付けが多いため、全体のリネーム難読化は自殺行為
  3. Source Generator の活用: 難読化するクラスについても、JSON通信を行うなら手動で JsonSerializerContext を定義し、名前の不一致をコンパイル時に埋める必要がある

結びに

「最新技術を全部盛り」しようとして地獄を見ましたが、最終的には「UIは標準、ロジックは難読化」という、メンテナンス性とセキュリティを両立した形に落ち着きました。

この苦闘の結果完成したアプリ「LichMenuLab」は、現在 Microsoft Store で公開中です。中身のロジックがどれだけぐちゃぐちゃに(難読化)されているか、興味がある方はぜひ覗いてみてください(笑)。


LichMenuLab:タブ付きリッチメニュー簡単作成
https://apps.microsoft.com/detail/9NBD0H4LQNX1


1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?