「新規 .NET MAUI プロジェクトに Plugin.Firebase.Analytics を追加したら、Clean → Rebuild でビルドが進まず固まる」。この現象は、特に Windows 環境で “長いパス” とビルドキャッシュが重なったときに起きやすい落とし穴です。本稿では原因の正体、最短で復旧する手順、再発防止の設計・運用のコツ、CI/CD への落とし込みまでを一気通貫でまとめます。macOS の注意点やスクリプト例も網羅しています。
症状の概要
次の操作で高確率に再現します。
- .NET MAUI の新規プロジェクトを作成
- NuGet パッケージをすべて最新化
Plugin.Firebase.Analyticsを追加- Clean → Rebuild を実行すると、復元(Restore)やビルドが途中で止まる/終わらない
想定環境は Windows 10/11 + Visual Studio、macOS + Visual Studio / VS Code。企業環境やモノリポ構成など、プロジェクトルートが深い階層(C:\Users\<name>\source\repos\Company.Project\... など)にあるケースで特に発生しやすく、Android ターゲットを含むとトランジティブ依存が増えてパスがさらに深くなります。Android 側のダウンロードキャッシュ(Xamarin/Gradle)や NuGet グローバルキャッシュが絡むと、Visual Studio 側でプロセスやファイルロックが発生し、固まりやすくなります。
原因の本質
- Windows のパス長(MAX_PATH)制限:既定では 260 文字制限が有効です。NuGet のパッケージ階層や Android の依存解決で、容易に 260 文字を超えます。
- Visual Studio の長いパス経由処理の弱さ:CLI(
dotnet)では通るパスでも、IDE 経由の復元・ビルドではロックや例外が握りつぶされ、画面上は「固まった」ように見えることがあります。 - 破損または古いビルドキャッシュ:NuGet、XamarinBuildDownload、Gradle、
bin/objに残った「長いパスの痕跡」や壊れた zip がリトライを誘発し、ビルドが進まなくなります。
最短で復旧するための要点(一覧)
| 手順 | 内容 | 補足 |
|---|---|---|
| ① Windows の「長いパス許可」を有効化 | レジストリまたはグループポリシーで LongPathsEnabled = 1 を設定 | Windows 既定の 260 文字制限を解除 |
| ② Visual Studio を終了 | IDE と関連プロセスを完全終了 | ビルドキャッシュのロックを防止 |
| ③ キャッシュ削除 | dotnet nuget locals all --clear/XamarinBuildDownloadCache ほかを削除 | macOS は ~/Library/Caches/XamarinBuildDownload を削除 |
④ bin/obj を全削除 | ソリューション配下の各プロジェクトで bin/obj を空に | 長パスの残骸が再現を誘発 |
| ⑤ CLI でパッケージ復元 | プロジェクトフォルダーで dotnet restore | この時点では Visual Studio をまだ開かない |
| ⑥ CLI でビルド確認 | dotnet build が成功するかを確認 | 成功後に Visual Studio を起動 |
| ⑦ 根本対策 | 短いパスへ移動/フォルダー名の短縮/グローバルキャッシュの短縮 | プラグイン依存が多いほど階層が深くなる |
具体的な操作手順(詳細解説)
Windows の「長いパス許可」を有効化(管理者権限)
グループポリシー(推奨)とレジストリ編集の 2 通りがあります。どちらも管理者権限が必要です。
- グループポリシー:
コンピューターの構成 → 管理用テンプレート → システム → ファイルシステム → 「Win32 の長いパスを有効にする」 を 有効 に設定。
反映はサインアウト/再起動が確実です(gpupdate /forceでも可)。 - レジストリ:次のどちらかを実行します。
reg add HKLM\SYSTEM\CurrentControlSet\Control\FileSystem ^ /v LongPathsEnabled /t REG_DWORD /d 1 /fまたは PowerShell(管理者)で:New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" ` -Name LongPathsEnabled -PropertyType DWord -Value 1 -Force
注意:企業端末でポリシーが固定されている場合、レジストリ変更がロールバックされることがあります。その場合は後述の「短いパス運用」や subst ドライブ、NUGET_PACKAGES の短縮で回避します。
Visual Studio を完全終了
IDE を閉じたあともバックグラウンドに devenv.exe、MSBuild.exe、VBCSCompiler.exe、adb.exe などが残ることがあります。タスクマネージャーで終了するか、次のコマンドで停止します(管理者で実行推奨)。
taskkill /IM devenv.exe /F
taskkill /IM msbuild.exe /F
taskkill /IM VBCSCompiler.exe /F
taskkill /IM adb.exe /F
キャッシュを削除(NuGet / Xamarin / Gradle)
まず NuGet のローカルキャッシュを空にします。
dotnet nuget locals all --clear
続いて、Xamarin/Android 関連のキャッシュを手動で削除します。
| OS | 削除対象の代表例 | メモ |
|---|---|---|
| Windows | %LOCALAPPDATA%\XamarinBuildDownloadCache%LOCALAPPDATA%\Xamarin\zips%USERPROFILE%\.nuget\packages(必要に応じて)%USERPROFILE%\.gradle\caches(Android を使う場合) | 容量が大きい場合は NuGet グローバルパッケージは残しても可 |
| macOS | ~/Library/Caches/XamarinBuildDownload~/.nuget/packages(必要に応じて)~/.gradle/caches(Android を使う場合) | Finder では不可視フォルダ。ターミナルで削除が確実 |
プロジェクトの bin/obj を完全に削除
ソリューション直下で以下を実行すると、すべての bin/obj をまとめて消せます。
PowerShell(Windows)
Get-ChildItem -Path . -Recurse -Directory -Include bin,obj |
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
bash(macOS)
find . -type d \( -name bin -o -name obj \) -prune -exec rm -rf {} +
CLI で復元 → ビルドを先に通す
IDE をまだ開かず、プロジェクトのルートで次を実行します。
dotnet restore
dotnet build -c Debug
長いパスを含むファイルにアクセスできないケースは IDE よりも先に CLI 側でエラーが顕在化します。必要に応じて詳細ログを採取します。
dotnet restore -v diag
dotnet build -v diag -bl:msbuild.binlog
.binlog は MSBuild Structured Log で解析できます。CLI が成功したら、Visual Studio を起動してプロジェクトを開きます。
根本対策:短いパスで運用する
- ソリューションをドライブ直下へ:
C:\src\MyAppやD:\a\appなど浅い階層へ移動します。 - フォルダー名/プロジェクト名の短縮:冗長な接頭辞・接尾辞を見直します。
- NuGet グローバルパッケージパスを短縮:一時的に
NUGET_PACKAGES=C:\nugetを設定。
永続化する場合はユーザー環境変数に追加します。 - Gradle キャッシュパスを短縮(Android):
GRADLE_USER_HOME=C:\gradleなどに設定。 substで仮想ドライブを作る:
長いルートをドライブ化して一気に短縮します。subst S: C:\Users\<name>\source\repos S:\Company.Project\...注:再起動で解除されるため、ログオンスクリプトに入れると安定。- Visual Studio を最新に:17.11 以降では長パス関連の改善が進んでいます。
チェックリスト(すばやく判断するために)
- Windows の LongPathsEnabled は 1 になっているか。
- Visual Studio(と関連プロセス)は完全終了しているか。
- NuGet/Xamarin/Gradle キャッシュをクリアしたか。
- すべてのプロジェクトの
bin/objを消したか。 - CLI で復元・ビルド を先に試し、通るか確認したか。
- パスを C:\src\… など短縮したか。
NUGET_PACKAGESを短くしたか。
トラブルシューティングを自動化するスクリプト
PowerShell(Windows)
# 管理者で実行推奨
$ErrorActionPreference = "SilentlyContinue"
# 1) 長いパスを有効化
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" `
-Name LongPathsEnabled -PropertyType DWord -Value 1 -Force | Out-Null
# 2) VS/関連プロセスの終了
"devenv","msbuild","VBCSCompiler","adb" | ForEach-Object {
taskkill /IM "$_.exe" /F | Out-Null
}
# 3) キャッシュ削除
dotnet nuget locals all --clear
$paths = @(
"$env:LOCALAPPDATA\XamarinBuildDownloadCache",
"$env:LOCALAPPDATA\Xamarin\zips",
"$env:USERPROFILE.gradle\caches" # Android を使う場合
)
foreach ($p in $paths) { if (Test-Path $p) { Remove-Item $p -Recurse -Force } }
# 4) bin/obj 削除
Get-ChildItem -Path . -Recurse -Directory -Include bin,obj |
Remove-Item -Recurse -Force
# 5) 復元 & 6) ビルド
dotnet restore
dotnet build -c Debug
bash(macOS)
#!/usr/bin/env bash
set -euo pipefail
# 2) VS/関連プロセスは手動終了(VS for Mac / dotnet など)
# 3) キャッシュ削除
dotnet nuget locals all --clear || true
rm -rf ~/Library/Caches/XamarinBuildDownload || true
rm -rf ~/.gradle/caches || true
# 4) bin/obj 削除
find . -type d ( -name bin -o -name obj ) -prune -exec rm -rf {} +
# 5) 復元 & 6) ビルド
dotnet restore
dotnet build -c Debug
CI/CD(Windows ビルドエージェント)への組み込み例
Windows Runner は管理者権限の制約でレジストリ変更が難しい場合があるため、短いパス+環境変数での短縮 を徹底します。
name: build-maui-windows
on: [push]
jobs:
build:
runs-on: windows-latest
env:
NUGET_PACKAGES: C:\nuget
GRADLE_USER_HOME: C:\gradle
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Short working dir
run: |
mkdir C:\src
robocopy . C:\src /E /NFL /NDL /NJH /NJS /NC /NS
echo "::set-output name=work::C:\src"
- name: Clear caches
shell: pwsh
run: |
dotnet nuget locals all --clear
if (Test-Path "$env:LOCALAPPDATA\XamarinBuildDownloadCache") {
Remove-Item "$env:LOCALAPPDATA\XamarinBuildDownloadCache" -Recurse -Force
}
- name: Restore
working-directory: C:\src
run: dotnet restore
- name: Build
working-directory: C:\src
run: dotnet build -c Release -bl:msbuild.binlog
Runner の作業ディレクトリを C:\src に複製して浅くするのがポイントです。ログ収集(-bl)も合わせると原因追跡が容易です。
長いパスを素早く検出するワンライナー
プロジェクト内に 240 文字超のパスがないかを抽出します(警戒域 240 文字)。
# Windows PowerShell
Get-ChildItem -Path . -Recurse | Where-Object {
$_.PSIsContainer -eq $false -and $_.FullName.Length -gt 240
} | Select-Object FullName | Out-File .\longpaths.txt
IDE が扱えない可能性のあるファイルを longpaths.txt に可視化できます。ファイル名やディレクトリ名を短縮する指標として活用してください。
Android ビルドで深くなりがちなディレクトリ
| ディレクトリ | 例 | 備考 |
|---|---|---|
| NuGet グローバル | %USERPROFILE%\.nuget\packages\... | パッケージ名・バージョン・ターゲットフレームワークで深くなる |
| XamarinBuildDownload | %LOCALAPPDATA%\XamarinBuildDownloadCache\... | zip 展開のパスが長くなりやすい |
| Gradle キャッシュ | %USERPROFILE%\.gradle\caches\... | 依存の識別子・バージョンで増殖 |
プロジェクト obj | <proj>\obj\Debug\net8.0-android\... | AOT/リンク時にさらに深くなる |
macOS での注意点
- OS としてパス長の制限は厳格ではない一方、XamarinBuildDownload の破損 や 古いキャッシュ があると類似症状が起こります。まずはキャッシュ削除 → CLI 復元・ビルドの順で切り分けます。
- Xcode/Android SDK のパスにスペースや非 ASCII が入ると、ツールチェーンによっては不具合の一因になることがあります。ホーム直下の短いパス(例:
~/sdk)に寄せると安定します。
代替・回避策の検討ポイント
- パッケージの絞り込み:
Plugin.Firebase系は便利な反面、依存が多くなりがちです。使わない機能は外す、必要最小限の構成にすることでパス深度とビルド時間を削減できます。 - Push 通知のみが目的 の場合は、
Shiny.FCMなど別実装で代替し、Analytics を後付け検討する構成も有効です。 - ネイティブ SDK 直接統合:どうしても Analytics のみを軽量に入れたい場合、プラットフォームごとにネイティブ SDK を直接バインドする方法もあります(導入・保守コストは上がります)。
FAQ
Q. Visual Studio でだけ固まり、CLI だと通るのはなぜ?
A. IDE 内部の拡張・プロセス間通信・ログビューなど、CLI より「長いパス」をたどる箇所が多く、例外が UI に現れにくいことがあります。CLI で先に成功させる のが最短の現実解です。
Q. 管理者権限がなく LongPathsEnabled を有効化できません。
A. リポジトリをドライブ直下へ移動、NUGET_PACKAGES を短縮、subst ドライブで短縮、といった パス設計 で回避できます。
Q. それでも改善しません。
A. 依存の更新・ダウングレードで変化が出る場合があります。Directory.Packages.props でバージョンを固定し、-bl で取得した .binlog を確認。bin/obj を都度クリーンし、Android ターゲットの有無で差が出るかも切り分けます。
Q. 長いパス以外に気を付ける点は?
A. 非 ASCII(日本語・スペース)を含むパスは一部ツールで問題になりやすい傾向があります。英数字のみ・短いパスを基本方針にするとトラブルが激減します。
再発防止の設計指針
- ルートを浅く、名前は短く:
C:\src\app、D:\a\appなど。 - 環境変数でキャッシュを短縮:
NUGET_PACKAGES、GRADLE_USER_HOMEを短いディレクトリへ。 - SDK/Workload を定期更新:.NET/Android/iOS のワークロードをこまめに更新し、破損時は “repair” ではなく再インストールも検討。
- IDE は最新安定版:Visual Studio は 17.11 以降を推奨。更新のたびに “長いパス改善” の恩恵が増えています。
まとめ
Plugin.Firebase.Analytics 追加後に .NET MAUI のビルドが固まる主因は、Windows のパス長制限 と キャッシュの不整合 の同時発生です。最短復旧は、「長パス許可 → キャッシュクリア → CLI で復元とビルド」 の 3 ステップ。加えて 短いパス設計(ルート直下運用、環境変数でのキャッシュ短縮、subst 活用)を徹底すれば、再発確率を劇的に下げられます。macOS では OS 制限こそ緩いものの、Xamarin/Gradle キャッシュの破損が同様の症状を生むため、同じ手順でのクリーンアップが有効です。CI/CD では「短い作業ディレクトリ+キャッシュ短縮+CLI ビルド」をテンプレ化しておくと、環境差異に強い安定したパイプラインになります。
追加のヒント
- Visual Studio を開く前に CLI を成功させる:IDE が関与しない純粋なビルドで成功を確認してから IDE を起動すると、トラブルの再現率が下がります。
- ロングパス検出を CI に組み込む:
FullName.Length > 240のファイルを検査し、検出時に警告を出すだけでも効果があります。 - binlog を常に採取:問題発生時に原因追跡が即座に可能になります。
実行順のサマリ(貼って使えるチェック表)
| チェック | アクション | 状態 |
|---|---|---|
| 長いパス許可 | LongPathsEnabled=1 / GPO 有効 | □ 済 |
| VS 終了 | devenv/msbuild/adb 停止 | □ 済 |
| キャッシュ削除 | NuGet / Xamarin / Gradle | □ 済 |
| bin/obj 削除 | すべてのプロジェクトで空に | □ 済 |
| CLI 復元 | dotnet restore | □ 済 |
| CLI ビルド | dotnet build / -bl | □ 済 |
| 短いパスへ移動 | C:\src 等、環境変数短縮 | □ 済 |
最終結論
多くの環境で、上記の流れを順に実行するだけでビルド停止は解消します。特に Windows では「長いパスを許可する」→「キャッシュを空にする」→「CLI でビルドを通す」という順番が効果的です。プロジェクトを浅いパスで運用する習慣をつけ、CI/CD でも短いパスとキャッシュ短縮を標準にすれば、Plugin.Firebase.Analytics に限らず、依存の多いモバイル開発全般で安定性が向上します。

コメント