Visual Studio の .NET MAUI プロジェクトを iOS シミュレーター向けにビルドしたときだけ「cswinrt.rsp が error code 1」で失敗する――そんな現象に悩んでいませんか? 本記事では、原因となる Microsoft.Windows.CsWinRT の設定ミスと、具体的な解決手順・再発防止策を詳しく解説します。
iOSシミュレーターだけ「cswinrt.rsp error code 1」で落ちる問題の全体像
今回取り上げるケースは、次のような環境・症状です。
| 項目 | 内容 |
|---|---|
| 開発環境 | Windows 上の Visual Studio から Mac にペアリングして .NET MAUI をビルド |
| ビルド対象 | iOS シミュレーター向けのビルドのみ失敗(実機 iPhone・Android は成功) |
| 主なエラー | Path ‘18.2’ is not a file or directory cswinrt.exe “…Generated Files\CsWinRT\cswinrt.rsp” exited with code 1 |
| プロジェクト設定 | Microsoft.Windows.CsWinRT 2.2.0 を PackageReference していた |
| 比較対象 | ダミーの MAUI プロジェクト(CsWinRT 参照なし)は iOS シミュレーターで正常ビルド |
| 周辺情報 | Xcode 14.2(iOS 16.2 まで)だが、ログに iOS 18.2 相当の数値 “18.2” が現れる |
ぱっと見では、
- プロビジョニングプロファイルがおかしい?
- Xcode が古くて iOS バージョンが合っていない?
と疑いたくなりますが、実際の原因は「Windows 専用の CsWinRT パッケージが iOS ビルドにも適用されてしまっている」ことでした。
エラーメッセージを分解して読み解く
まずは、代表的なログの一部を整理してみます。
Path '18.2' is not a file or directory
...
"...obj\Debug\net8.0-ios\iossimulator-x64\Generated Files\CsWinRT\cswinrt.rsp"
...
cswinrt.exe @"...cswinrt.rsp" exited with code 1
| メッセージ | 意味・ポイント |
|---|---|
| Path ‘18.2’ is not a file or directory | cswinrt.exe に渡されたパラメーター「18.2」がファイルパスとして解釈され、存在しないためエラー |
| cswinrt.exe … exited with code 1 | WinRT 射影ツール CsWinRT の実行に失敗。0 以外の終了コードはエラー |
| Generated Files\CsWinRT\cswinrt.rsp | MSBuild が CsWinRT 用のレスポンスファイル(パラメーター一覧)を生成しているサイン |
つまり、
- iOS ビルドの途中で CsWinRT のターゲットが走っている
- iOS のバージョン(18.2 等)が CsWinRT の入力引数に紛れ込み、「パス扱い」されてしまっている
という構図になっています。
実際に生成された cswinrt.rsp を覗くと、例えば次のような内容になっているはずです(例):
-target net8.0
-input 18.2
...
-input に OS バージョンがそのまま入っており、これをファイルパスだと思い込んだ CsWinRT が「そんなファイル(18.2)は無い」と怒っている、というわけです。
そもそも CsWinRT とは何か? なぜ iOS で動くのか?
Microsoft.Windows.CsWinRT は、C# から Windows Runtime(WinRT)API を扱うための射影ツールです。通常は次のような用途で使われます。
- WinUI 3 / Windows App SDK アプリで WinRT API を利用する
- 既存の Windows ランタイムコンポーネントを C# から参照する
つまり完全に Windows 専用のパッケージであり、
- Android
- iOS / macOS
- その他の非 Windows プラットフォーム
では通常一切使われません。しかし .NET MAUI のようなマルチターゲットプロジェクトの場合、
.csprojに条件無しでPackageReference Include="Microsoft.Windows.CsWinRT"と書く
と、すべてのターゲットフレームワーク(TFM)に対して CsWinRT の MSBuild ターゲットが有効になってしまいます。
その結果、
net8.0-androidのビルドでも CsWinRT が動こうとするnet8.0-ios(シミュレーター含む)のビルドでも CsWinRT が動こうとする
という不自然な状態が起き、今回のような「Path ‘18.2’ is not a file or directory」エラーにつながります。
iOS シミュレーターのバージョン「18.2」がなぜ CsWinRT に渡るのか
iOS のターゲットプラットフォームは、プロジェクトやビルド設定の中で数値として扱われます。例えば、
- iOS 16.2 →
16.2 - iOS 18.2 →
18.2
といった具合です。この値が MSBuild のプロパティ経由で CsWinRT のタスクに渡され、レスポンスファイル cswinrt.rsp の -input に紛れ込んでしまうと、CsWinRT の側からは
「-input に指定されたパス 18.2 のファイルが見つからない」
としか見えません。そのため、Xcode のバージョン(例:14.2)や、iOS シミュレーターで実際に選べるバージョン(例:16.2)とは直接の関係はありません。
ポイントは、
- iOS のバージョンが「ファイルパス」として扱われている
- そもそも iOS ビルドで CsWinRT が実行されていることがおかしい
という 2 点です。
原因の本質:Windows 専用パッケージが iOS ビルドにも効いている
ここまでを整理すると、原因は非常にシンプルです。
原因:
Windows 向けの Microsoft.Windows.CsWinRT パッケージ参照が、iOS など非 Windows のターゲットにも無条件に適用されているため、iOS ビルドで CsWinRT のターゲットが走ってエラーになっている。
これをもう少し MSBuild 的に言い換えると、
- MAUI プロジェクトは
TargetFrameworksによって複数の TFM(例:net8.0-android;net8.0-ios;net8.0-windows10.0.19041.0)を宣言している - そのうち Windows のみで使うべき
Microsoft.Windows.CsWinRTを、<ItemGroup>直下に無条件で書いている - 結果として、すべての TFM で CsWinRT 関連のターゲットが Import される
という状態です。
.csproj の例で見る「悪い書き方」と「良い書き方」
悪い書き方(今回問題になった形)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-windows10.0.19041.0</TargetFrameworks>
<UseMaui>true</UseMaui>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
</ItemGroup>
</Project>
この書き方だと、Android / iOS / Windows のすべてで CsWinRT が有効になり、iOS シミュレーターのビルド時にも cswinrt.exe が実行されてしまいます。
良い書き方その1:Windows をターゲットにしていない場合
Windows を対象としていない .NET MAUI アプリなら、そもそも CsWinRT は不要です。最もシンプルな対処は、
- プロジェクトから CsWinRT の参照を削除する
ことです。
<ItemGroup>
<!-- Microsoft.Windows.CsWinRT の行を削除する -->
</ItemGroup>
NuGet パッケージマネージャーからアンインストールしただけでは .csproj に行が残ることもあるため、テキストエディタで .csproj を直接開いて削除することをおすすめします。
良い書き方その2:Windows もターゲットにしたい場合
Windows もターゲットにしたい場合は、Windows のときだけ CsWinRT を参照するよう条件を付けます。
代表的には次の 2 パターンです。
パターンA:TargetPlatformIdentifier で Windows を判定
<ItemGroup Condition="'$(TargetPlatformIdentifier)'=='Windows'">
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
</ItemGroup>
こうすることで、
- Windows ビルドのときだけ CsWinRT が有効
- Android / iOS / macOS では CsWinRT のターゲットが一切走らない
という状態になります。
パターンB:特定の TFM にだけ適用する
Windows の TFM を明示的に指定している場合は、TargetFramework ベースで条件付けすることもできます。
<ItemGroup Condition="'$(TargetFramework)'=='net9.0-windows10.0.19041.0'">
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
</ItemGroup>
MAUI では net8.0-windows10.0.19041.0 のような TFM を使うことが多いので、自分のプロジェクトの TFM に合わせて値を変更してください。
実際の対処手順:iOS シミュレーターのビルドを通すまで
ここからは、手を動かすときの手順を、できるだけ迷わないようにまとめます。
手順1:CsWinRT の参照が残っていないか確認する
- Visual Studio で MAUI プロジェクトを開く。
- ソリューションエクスプローラーで対象プロジェクトを右クリックし、「プロジェクト ファイルの編集」を選択。
PackageReferenceの中に次のような行がないか探す。<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
もし見つかったら、
- Windows をターゲットにしない → 削除する
- Windows もターゲットにする → 条件付きの ItemGroup に移動する
という方針をとります。
手順2:Windows ターゲットの有無に応じて設定を変更
| やりたいこと | 設定例 |
|---|---|
| モバイル専用(Android / iOS のみ) | CsWinRT の PackageReference を完全に削除 |
| MAUI で Windows もサポートする | <ItemGroup Condition="'$(TargetPlatformIdentifier)'=='Windows'"> で CsWinRT を包む |
| Windows デスクトップ専用プロジェクト | MAUI ではなく WinUI / WPF 等なら、逆に iOS / Android をターゲットにしない |
手順3:bin / obj を削除してクリーンビルドする
プロジェクトファイルを書き換えたら、古い生成物が残らないようにクリーンビルドを行うことが重要です。
- Visual Studio を一度閉じる(任意ですがおすすめ)。
- エクスプローラーでプロジェクトフォルダーを開き、
binとobjフォルダーを削除する。 - 再度 Visual Studio を開き、ソリューションを読み込む。
- ビルド構成(Debug/Release)を確認し、iOS シミュレーターを選択してからビルドを実行する。
CLI が使える場合は、次のようなコマンドでキャッシュをきれいにしておくのも有効です。
dotnet nuget locals all --clear
dotnet workload restore
ここまで実施すれば、iOS シミュレーター向けのビルドは正常に完了するはずです。
Provisioning や Xcode は今回の原因ではない
モバイル開発では、ビルドエラーが出ると何かと「プロビジョニングプロファイル」や「Xcode のバージョン」が疑われがちですが、今回のケースではどちらも直接の原因ではありません。
- シミュレーター実行にプロビジョニングプロファイルは基本不要です。実機 iPhone 向け配布のときに必要になります。
- 今回の失敗は、Xcode が古くて iOS 18.2 が存在しないからではなく、iOS バージョンの数値を CsWinRT が「ファイルパス」と誤解していることが問題です。
そのため、プロビジョニングや Xcode をいじる前に、
「iOS ビルドで CsWinRT が走っていないか?」
をチェックすることが重要です。
obj フォルダーで「CsWinRT が混入していないか」を素早く確認する方法
ビルドのたびに膨大なログを眺めるのはつらいので、次のように obj フォルダーを確認する方法も有効です。
- iOS シミュレーター向けにビルドを実行。
- プロジェクトの
obj\Debug\net8.0-ios\iossimulator-xxx(構成やアーキテクチャによってパスは多少異なる)を開く。 - その中に
Generated Files\CsWinRTフォルダーが生成されていないか確認。
もし Generated Files\CsWinRT 配下に cswinrt.rsp が生成されている場合、
- iOS ビルドでも CsWinRT のターゲットが動いている
と判断できます。その場合は、本記事で紹介したように「CsWinRT の参照削除または Windows 限定化」の対応が必要です。
再発防止のためのチェックリスト
同じ落とし穴にはまらないよう、.NET MAUI / マルチターゲットプロジェクトを運用するときのチェックポイントをまとめておきます。
Windows 専用パッケージの扱い
- CsWinRT のようなWindows 専用パッケージは、必ず条件付きで参照する。
TargetPlatformIdentifier=='Windows'やTargetFrameworkの条件を利用して、Windows 以外の TFM では無効になるようにする。
.csproj と Directory.Packages.props の両方を見る
中央集約されたパッケージ管理(Directory.Packages.props)を使っている場合、
.csprojには書いていないのに、実はDirectory.Packages.propsに CsWinRT がいる
というパターンもあります。次の 2 つをセットで確認しましょう。
- プロジェクト直下の
.csproj - ソリューションルートなどにある
Directory.Packages.props
いずれかに無条件な CsWinRT の参照があれば、Windows 限定の条件を付けるか、もしくは削除すべきかどうか再検討する必要があります。
ビルドが急に失敗し始めたときの基本動作
obj/binを完全削除してから再ビルドする。- 最近追加したパッケージ、特に「Windows」や「WinRT」を含む名前のものを疑う。
- MSBuild の診断ログ(
/blや ログ詳細度=診断)を出力し、どのターゲットが走っているかを確認する。
| 症状 | まず見るポイント |
|---|---|
| iOS シミュレーターだけビルド失敗 | obj 配下に Windows 由来の生成物(CsWinRT など)が紛れ込んでいないか |
| Android / iOS の両方で似たエラー | マルチターゲットパッケージが全 TFM に効いていないか |
| Windows だけ失敗 | Windows 専用の Condition が正しく書かれているか、必要なパッケージが足りているか |
まとめ:原因は「Windows 向けパッケージの無条件参照」
今回の「iOS シミュレーターでだけ cswinrt.rsp が error code 1 で落ちる」問題のポイントを整理すると、次の通りです。
- エラーの正体は、iOS ビルド時に CsWinRT が誤って実行されていること。
- iOS のターゲットバージョン(例:18.2)が CsWinRT の
-inputに渡され、ファイルパスと誤解されることで「Path ‘18.2’ is not a file or directory」が発生している。 - 原因は、Microsoft.Windows.CsWinRT の PackageReference が非 Windows TFM にも無条件で効いていること。
- 対処は、CsWinRT の参照を削除するか、Windows のときだけ有効になるよう条件を付けること。
- プロビジョニングプロファイルや Xcode のバージョンは今回のエラーとは無関係。
.NET MAUI のようなクロスプラットフォーム開発では、「特定プラットフォーム専用パッケージ」の扱いが非常に重要です。一見便利そうなパッケージでも、どのプラットフォーム向けなのかを意識せずに追加すると、今回のように別のプラットフォームのビルドを壊してしまうことがあります。
もしあなたのプロジェクトでも、
- iOS シミュレーターだけビルドが通らない
- ログに
cswinrt.exeやcswinrt.rspが出てくる
という状況になっているなら、ぜひ一度 .csproj と Directory.Packages.props を開き、Microsoft.Windows.CsWinRT の参照が紛れ込んでいないかを確認してみてください。無条件参照を整理するだけで、嘘のようにビルドが通るようになるはずです。

コメント