-
Notifications
You must be signed in to change notification settings - Fork 0
MS_NuGetPackageManagement
- 戻る(NuGet)
- NuGet を使用したパッケージ管理
- NuGetパッケージの開発と公開
Microsoft Learn を参照。
Microsoft Learn を参照。
移行メモ(表記): 原文の「doscs、learnを参照。」は
**docs(現 Microsoft Learn)**の入力誤りと判断し、
統合して「Microsoft Learn を参照。」に修正した。
補足(現在の操作手段/最新化): 本ページの記述は
packages.config+nuget.exe+ パッケージ マネージャー コンソール
を前提としている。現在は次の 3 系統がある。
手段 対象 備考 dotnetCLISDK スタイル プロジェクト 現在の第一候補(dotnetコマンド) パッケージ マネージャー UI 両方 Visual Studio の GUI パッケージ マネージャー コンソール(PowerShell) 主に packages.configInstall-Package等nuget.exepackages.config系レガシー dotnet add package Newtonsoft.Json --version 13.0.3 dotnet remove package Newtonsoft.Json dotnet list package --outdated # 更新可能なものを列挙 dotnet list package --vulnerable # 脆弱性のあるものを列挙 dotnet restore
dotnet list package --vulnerableは、
依存パッケージの既知の脆弱性を検出する。
CI に組み込んでおくと、サプライ チェーン上のリスクを継続的に検知できる。
GAC に登録されるような従来のMicrosoft Windows Installerで
配布されるようなパッケージは、今までどおり GAC に登録されているものを参照する。
GAC に登録されていないパッケージ (OSS ライブラリなど) は、
もちろん個別にパッケージをダウンロードし、それを参照することもできる。
しかし、そのパッケージが NuGet に登録されていれば、
NuGet のメリットを享受するために NuGet 経由でインストールするのが良いのではないかと思われる。
GAC にも NuGet にも登録されていないパッケージを使用する場合は、
個別にダウンロードし、プロジェクトから参照させる。
NuGet でインストールしたパッケージ (*.dll) は、GAC には含まれない。
このため、NuGet でインストールしたパッケージをアプリケーションで使用する場合、
「ローカルコピー」は必ず「True」にしておくこと。
補足(.NET Core 以降では GAC が無い/最新化): 本節の 3 分類は
.NET Framework 前提である。
.NET Framework .NET Core / .NET GAC あり(共有配置) 廃止 参照の解決 GAC → binの順deps.jsonに従うローカルコピー 明示的に True にする必要 既定でアプリ配下に出力 フレームワーク マシンに 1 つ(の系列) アプリごと(SCD なら同梱) GAC 廃止の意味は大きく、
「マシン全体で 1 つの版を共有する」という前提そのものが無くなった。
これにより、
- アプリごとに異なる版のライブラリを使える(DLL Hell の解消)
- 管理者権限なしで配置できる
- アンインストール漏れによる残骸が生じない
という利点が得られた
(詳細は .NETアセンブリ / アセンブリ)。ただし .NET Core でも、
ビルド出力に NuGet 参照がコピーされないという別の現象がある
(後述の.NET Core の場合を参照)。
補足(この節は
packages.config固有): 以下は、
packages.config方式で「参照設定 /packages.config/packagesフォルダ」
の 3 つが二重管理になっていることから生じる問題群である。【packages.config 方式】3 箇所を整合させる必要がある .csproj の <Reference><HintPath> ← 参照設定 packages.config ← 入れたパッケージの一覧 packages\ フォルダ ← 実体 【PackageReference 方式】1 箇所だけ .csproj の <PackageReference> ← これだけ (実体はグローバル パッケージ フォルダ %USERPROFILE%\.nuget\packages)PackageReference に移行すれば、本節の問題はほぼすべて消える。
既存プロジェクトの移行方法は後述の Package Reference を参照。
- 参照設定を解除したパッケージを使用していない場合は、通る。
- (ただし、参照設定、packages.config、packages フォルダの整合性は崩れたまま)
- 既にインストールされています。というメッセージが表示され、変わりなし。
- (ただし、参照設定、packages.config、packages フォルダの整合性は崩れたまま)
-
当該パッケージに更新がなかった場合
- 更新はありません。というメッセージが表示され、変わりなし。
- (参照設定、packages.config、packages フォルダの整合性は崩れたまま)
-
当該パッケージに更新があった場合
- 問題なく更新が行われる。
- 参照設定、packages.config、packages フォルダの整合性も直る。
- packages.config からは削除されるが、
packages フォルダから削除する際に、正常に削除できなかった旨の警告が出る。 - Visual Studio を再起動し、プロジェクトを再度開くと、
そのとき packages フォルダからパッケージが削除される。 - 参照設定、packages.config、packages フォルダの整合性も直る。
消したパッケージが自動的に復元され、ビルドは正常終了する。
パッケージの復元は、Visual Studio や、MSBuild でビルドした際、
足りないパッケージを自動的に NuGet サイトからダウンロードする機能である。
- Visual Studio の [ツール]-[オプション] でオプション画面を開く。
- ツリーの中から、[NuGet パッケージ マネージャー]-[全般] を選択する。
- 「足りないパッケージをダウンロードすることを NuGet に許可」にチェックを入れる。
さらに、MSBuild などのコマンドラインツールでのビルド時に、
足りないパッケージをダウンロードするには、以下の設定を行う。
- Visual Studio の [ソリューション エクスプローラー] を右クリックし、
「Enable NuGet Package Restore」を選択する。
これにより、ソリューションフォルダ直下に**「.nuget」**フォルダができ、
コマンドラインツールでのビルド時でも、足りないパッケージがあれば、
ダウンロードしてくれる(MSBuild だけでなく、devenv によるビルドでも有効)。
※ この動作は、Visual Studio 2015 (NuGet 2.7) で変更されている。
上記と同様、パッケージが復元され、ビルドは正常終了する。
補足(
.nugetフォルダ方式は廃止済み): 上記の
「Enable NuGet Package Restore」による.nugetフォルダ方式
(MSBuild 統合による復元)は、NuGet 2.7 で非推奨になった
(後述の Visual Studio 2015)。現在は **「自動復元」**が既定で、
ビルドの前に NuGet 自身が復元を行うため、
.nuget\NuGet.targetsをプロジェクトに取り込む必要はない。# CI などで明示的に復元する場合 dotnet restore # SDK スタイル nuget restore Foo.sln # packages.config 系 msbuild -t:restore # MSBuild 統合古いリポジトリを開いたときに
.nugetフォルダが残っていたら、
マイグレーションが済んでいないサインである。
- Install-Package
成功 (ふたたび packages.config に <package> が生成される) - Update-Package
失敗 (パッケージがインストールされていないとのメッセージが表示される) - Uninstall-Package
警告 (packages フォルダから削除する際に、正常に削除できなかった旨の警告が出る。
Visual Studio を再起動し、プロジェクトを再度開くと、
そのとき packages フォルダからパッケージが削除される)
-
存在するバージョン番号の場合
ビルドは成功し、編集したバージョン番号のパッケージが packages フォルダに格納される。
このとき、編集前のバージョンのパッケージは packages フォルダからは削除されない。
このため、以下の不整合が起きる。- packages フォルダに、バージョンの異なる 2 つのパッケージが混在する。
- 参照設定も解除されないので、プロジェクトは編集前のバージョンのパッケージを参照し続ける。
- このため、packages.config に書かれたバージョン番号と、
実際に参照しているバージョン番号が一致しないことになる。
-
存在しないバージョン番号の場合
「NuGet パッケージの復元がプロジェクト {プロジェクト名} に対して失敗しました」
というメッセージは表示されるが、- ビルド自体は成功する(編集前のバージョン番号のパッケージの削除が行われないため。)。
- この場合も、以下の不整合が起きる。
- packages フォルダには、編集前のバージョン番号のパッケージのみが残る。
- 参照設定も解除されないので、プロジェクトは編集前のバージョンのパッケージを参照し続ける。
- このため、packages.config に書かれたバージョン番号と、
実際に参照しているバージョン番号が一致しないことになる。
補足(この一連の検証の結論): 原文が丹念に検証している通り、
packages.configを手で編集しても、参照設定(.csproj)は追従しない。
結果、**「宣言と実体がずれたままビルドが通る」**という
最も厄介な状態が生まれる。見分け方:
# .csproj の HintPath と packages.config のバージョンを突き合わせる grep -o 'packages\\[^\\]*\\' *.csproj | sort -u grep -o 'version="[^"]*"' packages.config | sort -u確実に直す手順は、原文の検証結果に沿えば
Uninstall-Package→Install-Package(またはUpdate-Package)である
(どちらも 3 者の整合性を回復させる)。根本的な対処は PackageReference への移行で、
こちらは.csprojの 1 箇所しか無いため、ずれようがない。
同様に参照設定との整合性が崩れる。
- プロジェクトファイル(.csproj、.vbproj)内の<HintPath></HintPath>のタグを修正する。
- 若しくは、Uninstall-Package -> Install-Package を行う。
NuGet は、Install-Package を行った際に、バージョン間の問題を解決するために、
"assemblyBinding -> dependentAssembly -> bindingRedirect" を追加する。
このため、
- Update-Package
- Uninstall-Package -> Install-Package
によって package のバージョンを変更した場合、問題を起こすことがある。
この場合、一度、assemblyBinding section を削除した後に、
Add-BindingRedirect を実行して、bindingRedirect を再生成する。
補足(bindingRedirect とは何か): .NET Framework は
参照したアセンブリの版が完全一致することを要求する
(アセンブリ の厳密名による強いバインド)。
このため、あなたのアプリ ──> LibA 1.0 ──> Newtonsoft.Json 9.0 └───> LibB 2.0 ──> Newtonsoft.Json 13.0 → LibA は 9.0 を要求するが、実際に置かれているのは 13.0 → 「ファイルまたはアセンブリを読み込めませんでした」で落ちるという DLL Hell が起きる。
これを「9.0 の要求は 13.0 で満たす」と読み替えさせるのが
bindingRedirect(app.config/web.config)である。<dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" /> <bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" /> </dependentAssembly>NuGet がこれを自動生成するため、
パッケージのバージョンを上げ下げすると古い記述が残って矛盾する——
というのが原文の指摘する問題である。
対処(section を消してAdd-BindingRedirectで作り直す)は現在も有効。.NET Core 以降では、この問題自体が存在しない。
バインドの解決がdeps.jsonに基づき、
**「参照より新しい版があればそれを使う」**という緩やかな規則になったため、
bindingRedirectは不要になった。
.NET Framework から移行する動機の一つがここにある。
-
Updating Assembly Redirects with NuGet - Rick Strahl's Web Log
https://weblog.west-wind.com/posts/2014/Nov/29/Updating-Assembly-Redirects-with-NuGet -
NuGet versioning
- Part 1: taking on DLL Hell - David Ebbo
http://blog.davidebbo.com/2011/01/nuget-versioning-part-1-taking-on-dll.html - Part 2: the core algorithm - David Ebbo
http://blog.davidebbo.com/2011/01/nuget-versioning-part-2-core-algorithm.html - Part 3: unification via binding redirects - David Ebbo
http://blog.davidebbo.com/2011/01/nuget-versioning-part-3-unification-via.html
- Part 1: taking on DLL Hell - David Ebbo
-
初心者が迷ったNuGet Packageのバージョンを下げたら
app.configを掃除しなければイケナイという話 - tmori3y2のブログ
http://tmori3y2.hatenablog.com/entry/2016/02/07/235133- .nuspec は間違いの無いように書こう、もしくは MSBuild の詳細出力を確認する - kendik.net
http://kendik.hatenablog.com/entry/2015/01/27/221240
- .nuspec は間違いの無いように書こう、もしくは MSBuild の詳細出力を確認する - kendik.net
- nuget.config を用意し、親ディレクトリに配置、
ここに、repositoryPath を指定することで NuGet パッケージの DL 先を変更できそう。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="repositoryPath" value=".\sharedpackages" />
</config>
</configuration>-
なお、検証の結果、ソリューション分割によって、
NuGet パッケージの DL 先(packages)が分割される模様。
(既定では *.sln ファイルと同じ階層に packages フォルダができる) -
従って、このケースで packages を共有したい場合、
- 2つのソリューションのルート・ディレクトリに nuget.config を配置するか、
- 2つのソリューションの其々の上位ディレクトリに nuget.config を配置し、
同じ repositoryPath を指すか、
で、対応ができる。
- 以下は、2つの *.sln ファイル(ClassLibrary.sln、ConsoleApp1.sln)間で
packages を共有した例。
フォルダ/ファイル名 種類
-----------------------------------------------------------------------------------------------------
Root1 <Dir>
├ ClassLibrary <Dir>
| ├ ClassLibrary1 <Dir>
| | ├ Properties <Dir>
| | | └ AssemblyInfo.cs <File>
| | ├ Class1.cs <File>
| | ├ ClassLibrary1.csproj <File>
| | └ packages.config <File>
| ├ ClassLibrary2 <Dir>
| | ├ Properties <Dir>
| | | └ AssemblyInfo.cs <File>
| | ├ Class1.cs <File>
| | ├ ClassLibrary2.csproj <File>
| | └ packages.config <File>
| └ ClassLibrary.sln <File>
├ ConsoleApp1 <Dir>
| ├ ConsoleApp1 <Dir>
| | ├ Properties <Dir>
| | | └ AssemblyInfo.cs <File>
| | ├ App.config <File>
| | ├ ConsoleApp1.csproj <File>
| | ├ packages.config <File>
| | └ Program.cs <File>
| └ ConsoleApp1.sln <File>
├ sharedpackages <Dir>
| └ Newtonsoft.Json.10.0.3 <Dir>
| ├ lib <Dir>
| ├ tools <Dir>
| ├ LICENSE.md <File>
| └ Newtonsoft.Json.10.0.3.nupkg <File>
└ nuget.config <File>
補足(PackageReference では不要になる): この
「ソリューションごとにpackagesが分裂して重複ダウンロードされる」
という問題も、PackageReference 方式では発生しない。
packages.configPackageReference 実体の置き場所 .slnごとのpackages\ユーザー単位のグローバル フォルダ 既定のパス <sln>\packages%USERPROFILE%\.nuget\packages重複 ソリューション数だけ増える 1 つを共有 設定キー repositoryPathglobalPackagesFolder<!-- PackageReference 方式でグローバル フォルダを変える場合 --> <configuration> <config> <add key="globalPackagesFolder" value="D:\nuget-cache" /> </config> </configuration>
repositoryPathは PackageReference では効かないため、
移行後も古い設定が残っていると混乱のもとになる。なお、CI で毎回ダウンロードしたくない場合は、
NUGET_PACKAGES環境変数でキャッシュ場所を指定し、
ビルド エージェント間で共有するのが定石である。
-
.net - NuGetのパッケージの場所を変更することは可能ですか? - visual-studio | CODE Q&A [日本語]
https://code.i-harness.com/ja/q/3e7357 -
複数のソリューション間で NuGet のリポジトリを共有する - しばやん雑記
http://blog.shibayan.jp/entry/20150417/1429269753 -
NuGet の動作の構成
https://learn.microsoft.com/ja-jp/nuget/consume-packages/configuring-nuget-behavior
NuGet 自体のバージョンを(NuGet 2.7 以降に)上げると、リストア方法も変更になる。
この場合、以下のように、リストア方法をマイグレーションする必要がある。
- Issue #220 · OpenTouryoProject/OpenTouryo
This project references NuGet package(s) that are missing on this computer....
https://github.com/OpenTouryoProject/OpenTouryo/issues/220
-
c# - How do I Enable NuGet Package Restore in Visual Studio 2015 - Stack Overflow
http://stackoverflow.com/questions/27895504/how-do-i-enable-nuget-package-restore-in-visual-studio-2015 -
NuGet 2.7へアップグレードした場合のプロジェクトファイル変更方法(任意) - kkamegawa's weblog
http://kkamegawa.hatenablog.jp/entry/20130825/p1 -
NuGet Package Restore
https://learn.microsoft.com/ja-jp/nuget/consume-packages/package-restore
Visual Studio 2017 からは、packages.config ではなく、
Project ファイルに統合された Package Reference を使用できる。
- 新しい csproj 形式 | ++C++; // 未確認飛行 C ブログ
http://ufcpp.net/blog/2017/5/newcsproj/ - Visual Studio 2017 での NuGet アップデートが良い感じだった - しばやん雑記
http://blog.shibayan.jp/entry/20170201/1485878757
ただし、一部問題を観測している。
補足(移行手順/最新化): 現在は
packages.config→ PackageReference の移行が推奨されており、
Visual Studio に移行機能が用意されている。ソリューション エクスプローラーで packages.config を右クリック → [packages.config を PackageReference に移行する]移行によって得られるもの:
効果 内容 3 者の二重管理が消える .csproj1 箇所になる推移的依存が明示されなくなる 直接使うものだけ書けばよい ディスク使用量の削減 グローバル フォルダを共有 binの肥大化が減る必要なものだけ出力 dotnetCLI が使えるCI がシンプルになる 注意点:
install.ps1/uninstall.ps1を持つパッケージは動かない
(PackageReference は PowerShell スクリプトを実行しない)contentフォルダで設定ファイルを配るパッケージも同様
(contentFilesへの対応が必要)- 推移的依存が自動で解決されるため、
これまで明示されていた依存が.csprojから消える
(原文が .NET Core の場合 で触れる NU1701 等の
挙動差にもつながる)原文が指す「一部問題」(CS0246)も、
この推移的依存の扱いの違いに起因するものである。
-
.NET Core で、ビルド出力に NuGet リファレンスがコピーされない。
- 以下を csproj ファイルに追加すると NuGet リファレンスをビルド出力にコピーする。
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>-
参考
- c# - How to get .NET Core projects to copy NuGet references to build output? - Stack Overflow
https://stackoverflow.com/questions/43837638/how-to-get-net-core-projects-to-copy-nuget-references-to-build-output
- c# - How to get .NET Core projects to copy NuGet references to build output? - Stack Overflow
-
NuGet Warning NU1701
-
net から netcoreapp のパッケージを参照した場合などに発生する。
-
net と netstandard のアセンブリを同梱した NuGet パッケージでは、
dependencies - group - targetFrameworkで解決できる。 -
参考
- Several warnings building on .Net Core · Issue #559 · Azure/Azure-Functions
https://github.com/Azure/Azure-Functions/issues/559
- Several warnings building on .Net Core · Issue #559 · Azure/Azure-Functions
-
補足(
CopyLocalLockFileAssembliesが要る理由): .NET Core では、
dotnet buildの出力(bin\)に依存 DLL が入らないことがある。
これは「実行時にdeps.jsonを見てグローバル フォルダから解決する」
という設計のためで、不具合ではない。【dotnet run / dotnet publish】 deps.json 経由で解決される → 問題なし 【bin\ をそのままコピーして別の場所で動かす】 グローバル フォルダが無い → 見つからないこのため、
状況 対処 通常の配置 dotnet publishを使う(すべて揃う)クラス ライブラリを他所に渡す CopyLocalLockFileAssembliesプラグイン DLL を作る CopyLocalLockFileAssemblies+EnableDynamicLoading**原則は「
dotnet publishを使う」**であり、
CopyLocalLockFileAssembliesは
ビルド出力を直接配る必要がある場合の回避策と位置づけられる
(.NET Coreのデプロイ)。NU1701 は、
「.NET Framework 用のパッケージを .NET Core 系から参照した」
という警告である。動くこともあるが保証されないため、
netstandard2.0対応版があるか探す(第一候補)- 無ければ代替ライブラリを探す
- どうしても必要なら
NoWarnで抑止し、動作確認を厚くするという順で検討する。
-
.NET 用パッケージマネージャー NuGet のインストールと使い方
http://yohshiy.blog.fc2.com/blog-entry-236.html -
.NET開発の新標準「NuGet」入門 - @IT
- NuGet Gallery | Home
https://www.nuget.org/
現在登録されている NuGet パッケージを検索可能
- NuGet Docs
https://learn.microsoft.com/ja-jp/nuget/
NuGet の機能や使い方などのドキュメントを閲覧可能
-
NuGet パッケージ マネージャー UI リファレンス
https://learn.microsoft.com/ja-jp/nuget/consume-packages/install-use-packages-visual-studio -
NuGet パッケージ マネージャー コンソールのガイド
https://learn.microsoft.com/ja-jp/nuget/consume-packages/install-use-packages-powershell -
NuGet コマンド ライン インターフェイス (CLI) のリファレンス
https://learn.microsoft.com/ja-jp/nuget/reference/nuget-exe-cli-reference -
dotnet CLI での NuGet の操作
https://learn.microsoft.com/ja-jp/nuget/consume-packages/install-use-packages-dotnet-cli
- NuGet の Install-Package の PowerShell リファレンス
https://learn.microsoft.com/ja-jp/nuget/reference/ps-reference/ps-ref-install-package - NuGet の Update-Package の PowerShell リファレンス
https://learn.microsoft.com/ja-jp/nuget/reference/ps-reference/ps-ref-update-package - NuGet の Uninstall-Package の PowerShell リファレンス
https://learn.microsoft.com/ja-jp/nuget/reference/ps-reference/ps-ref-uninstall-package
- packages.config から PackageReference への移行
https://learn.microsoft.com/ja-jp/nuget/consume-packages/migrate-packages-config-to-package-reference - 中央パッケージ管理(Central Package Management)
https://learn.microsoft.com/ja-jp/nuget/consume-packages/central-package-management
Tags: 移行, .NET開発, デプロイ, NuGet
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。