MS_NuGetCS0246 - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki
- 戻る(NuGet)
Package Referenceに切り替え後、
プロジェクトをMSBuildでビルドしようとしたら
- CS0246 型または名前空間名 'xxxx' が見つかりませんでした。
using ディレクティブまたはアセンブリ参照が不足しています。 - CS0246 The type or namespace name 'xxxx' could not be found
(are you missing a using directive or an assembly reference?)
が出た。
補足(症状の特徴): Visual Studio では通るのに、
コマンド ライン(MSBuild.exe)では落ちる——というのが
本ページの症状の典型である。Visual Studio → ビルド成功 msbuild Foo.sln → CS0246 が大量に出る「型が見つからない」というメッセージから
ソースの問題と誤解しやすいが、実際は
パッケージの復元が行われていないことが原因である
(参照すべき DLL が存在しないため、型も見つからない)。
下記のような対策があったが、何れも効果は無かった。
- 以下をインストールする。
Install-Package Microsoft.VisualStudio.Setup.Configuration.Interop
- 以下の設定を追加する。
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>.NET Standard、.NET Coreだとバッチリ動いているが、
.NET Framework の方の実装は問題があるようなので、
.NET Framework 版は(、現時点では、)Package Reference に
しない方がイイ。
補足(この結論は現在では見直してよい/最新化): 原文の
「.NET Framework 版は PackageReference にしない方がイイ」という結論は、
本ページの執筆時点(VS 2017 初期)では妥当だったが、
現在は状況が改善している。
時期 状況 VS 2017 初期 packages.configからの移行が不安定。本ページの症状VS 2017 15.7 移行ツールが搭載され、実用的になる VS 2019 以降 packages.configは非推奨扱いに現在 PackageReference が既定(新規プロジェクト) 現在は .NET Framework でも PackageReference が推奨である。
移行によって得られる利点は
NuGetでインストールすると依存関係が増えすぎる問題 や
NuGet を使用したパッケージ管理 の通りで、大きい。ただし、移行できないケースは依然としてある。
阻害要因 内容 install.ps1を持つパッケージPackageReference では実行されない web.config.transform同上(設定が反映されない) content\でファイルを配るパッケージcontentFiles未対応のものがある古い SDK に依存するビルド環境 ビルド サーバーの更新が必要
RestoreProjectStyleは、
「.csprojにPackageReferenceが 1 つも無い状態で
PackageReference 方式として復元させたい」場合に使うプロパティで、
本症状の対処にはならない(原文の観測通り)。
nuget.exe restore を削除して、
MSBuild のオプションに以下を追加したら上手く動作した。
/t:Restore
※ NuGetリストア(ビルドスクリプト)を nuget.exe ではなく、
MSBuild で行うように変更されていたというオチ。
補足(これが正解/仕組みの説明): 原文の「オチ」が
本質的な原因である。復元の担当が方式によって異なる。
方式 復元を行うもの 復元先 packages.confignuget.exe restore<sln>\packages\PackageReference MSBuild の Restoreターゲットグローバル フォルダ + obj\project.assets.json【PackageReference で必要なもの】 obj\project.assets.json ← 参照の解決表。これが無いと型が見つからない obj\Foo.csproj.nuget.g.props / .targets これらは MSBuild の Restore ターゲットが生成する。 nuget.exe restore では(PackageReference 形式に対して)生成されない。つまり、
nuget.exe restoreを呼んでいる CI スクリプトは、
PackageReference 移行後は機能しなくなる。
Visual Studio は内部でRestoreを実行するため気付かない——
というのが「VS では通るのに CI で落ちる」の正体である。正しい書き方:
# ① MSBuild で復元してからビルド(.NET Framework も可) msbuild Foo.sln -t:Restore msbuild Foo.sln -t:Build -p:Configuration=Release # ② 1 コマンドにまとめる(-restore スイッチ) msbuild Foo.sln -restore -p:Configuration=Release # ③ SDK スタイルなら dotnet で完結(restore は暗黙に実行される) dotnet build Foo.sln -c Release
-t:Restore;Buildのようにセミコロンで繋ぐのは避ける。
復元で生成された.props/.targetsが
同一の MSBuild プロセスでは読み込まれないため、
結局同じエラーになる(別々に呼ぶか-restoreを使う)。ビルド スクリプトの整備は ビルドスクリプト も参照。
補足(切り分けの手順): CS0246 が出たら、まず次を確認する。
① obj\project.assets.json は存在するか? 無い → 復元が走っていない(対策2) ② 存在するが古い(.csproj より古い)? → 復元が最新でない。obj\ を消して再復元 ③ 存在し、最新。中に該当パッケージがあるか? 無い → PackageReference の記述漏れ、または復元先ソースの問題 ④ ある → 本当にソースの問題(using 漏れ、TFM 不一致)# 疑わしいときは obj/bin を消してから復元し直す Get-ChildItem -Recurse -Directory -Include obj,bin | Remove-Item -Recurse -Force msbuild Foo.sln -restore -p:Configuration=Release
-
Command line builds fail when UWP project.json project references PackageReference project · Issue #4804
https://github.com/NuGet/Home/issues/4804 -
Automatically use PackageReference mode if referencing a project that uses PackageReference · Issue #4581
https://github.com/NuGet/Home/issues/4581
- Issues with .NET Standard 2.0 with .NET Framework & NuGet · Issue #481
https://github.com/dotnet/standard/issues/481
- MSBuild を使用したパッケージの復元
https://learn.microsoft.com/ja-jp/nuget/consume-packages/package-restore#restore-using-msbuild - packages.config から PackageReference への移行
https://learn.microsoft.com/ja-jp/nuget/consume-packages/migrate-packages-config-to-package-reference
Tags: 移行, テスト, デバッグ, デプロイ, .NET開発