NuGet 自动包恢复对 MSBuild 不起作用

我正在尝试用 MSBuild 12.0构建一个缺少 packages内容(除了内部的 repositories.config)的解决方案。我希望它能在构建之前自动恢复所有丢失的包,但事实并非如此—— MsBuild 报告了大量的错误:

“您是否缺少 using 指令或汇编引用?”

NuGet Manager 是2.7(我在 Visual Studio 2013 about box 中看到了这一点)。我甚至试图通过 EnableNuGetPackageRestore=true参数-没有运气。我错过了什么?

133970 次浏览

该项目有一个 Packages.config文件,它包含了包的详细信息。

还有一个。包含 NuGet.exe 和 NuGet.target的 nuget 文件夹。如果文件中的任何一个丢失了,它将不会恢复丢失的包,并导致“您是丢失了 using 指令还是程序集引用?”错误

在3.3.0版本中更新了最新的官方 NuGet 文档

Package Restore Approaches

NuGet 提供了三种使用 包恢复的方法。


自动包还原 是 NuGet 团队推荐的在 Visual Studio 中进行包还原的方法,它是在 NuGet 2.7中引入的。 从 NuGet 2.7开始,NuGet Visual Studio 扩展集成到 Visual Studio 的构建事件中,并在构建开始时恢复丢失的包。默认情况下启用此特性,但如果需要,开发人员可以选择退出。


它是这样运作的:

  1. 在项目或解决方案生成时,VisualStudio 引发 在解决方案中开始构建。
  2. NuGet 对此事件作出回应 并检查解决方案中包含的 packages.config 文件。
  3. For each packages.config file found, its packages are enumerated and Checked for exists in the solution's packages folder.
  4. Any missing packages are downloaded from the user's configured (and enabled) package sources, respecting the order of the package sources.
  5. 在下载软件包时,它们被解压到解决方案的 包文件夹。

如果你已经安装了 Nuget 2.7 + ,选择一种方法来管理 Visual Studio 中的自动包还原是很重要的。

Two methods are available:

  1. (Nuget 2.7 +) : Visual Studio-> Tools-> Package Manager-> Package 管理器设置-> 启用自动包恢复
  2. (Nuget 2.6及以下版本)右键单击解决方案并单击“ Enable Package 为此解决方案还原”。


命令行包恢复 在从命令行构建解决方案时是必需的; 它是在 NuGet 的早期版本中引入的, 但是在 NuGet 2.7中得到了改进。

nuget.exe restore contoso.sln

MSBuild 集成包还原 方法是原始的 PackageRestore 实现,尽管 在许多情况下继续工作,它不包括完整的 其他两种方法处理的情况。

我花了一些时间才弄清楚整个情况,我想在这里分享一下。

VisualStudio 有两种使用包恢复的方法: 自动包恢复和 MSBuild-集成包恢复。“ MSBuild-IntegratedPackageRestore”在构建过程中还原可能在某些场景中引起问题的包。“自动包恢复”是由 NuGet 团队的 建议的方法

有几个步骤,使“自动包恢复”的工作:

  1. 在 Visual Studio 中,工具-> 扩展和更新,如果有更新的版本(2.7或更高版本) ,则升级 NuGet

  2. 如果使用 TFS,则在解决方案的。Nuget 文件夹,删除 NuGet.exe 和 NuGet.targes 文件。然后编辑 NuGet。配置不检入 NuGet 包:

    <configuration>
    <solution>
    <add key="disableSourceControlIntegration" value="true" />
    </solution>
    </configuration>
    

    如果您在签入解决方案的包文件夹到 TFS 之前,删除该文件夹并签入删除包文件夹。

    如果不使用 TFS,请删除.nuget 文件夹。

  3. In each project file (.csproj or .vbproj) in your solution, remove the line that references NuGet.targets file. The reference looks like this:

    <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
    

    删除解决方案中每个项目文件中的此行。

  4. 在 VisualStudio 菜单中,通过

    工具-> 选项-> 软件包管理器-> 一般或 工具-> NuGet 软件包管理器-> 软件包管理器设置

    请启用以下两个选项 1) 'Allow NuGet to download missing packages' 2)“在 Visual Studio 构建期间自动检查丢失的包”

  5. 通过以下步骤测试包还原配置

    • 保存解决方案并关闭 VisualStudio
    • 删除解决方案的包文件夹
    • 启动 VisualStudio,打开解决方案并重新生成它。

Nuget 的自动包恢复是 Visual Studio 的一个特性(从2013年开始) ,而不是 MSBuild。如果要从命令行还原包,则必须运行 nuget.exe restore

您还可以使用 Enable Nuget Package Restore 特性,但是这不再被 Nuget 人员推荐,因为它会对项目文件进行干扰性更改,并且如果您在另一个解决方案中构建这些项目,可能会导致问题。

如果您正在使用 VisualStudio2017或更高版本,其中包含 MSBuild15或更高版本的 你的. csproj 文件位于新的 PackageReference格式 ,则最简单的方法是使用 使用新的 MSBuildRestore目标


实际上没有人回答最初的问题,即“如何让 NuGet 包在使用 MSBuild 从命令行构建时自动恢复?”答案是: 除非您正在使用“ Enable NuGet 包恢复”选项(根据 这个参考现在已经不推荐使用该选项) ,否则就不能使用它(但请参见下文)。如果你想在 CI 服务器上进行自动构建,这很糟糕。

然而,还有一个略微迂回的方法来获得理想的行为:

  1. https://dist.nuget.org/win-x86-commandline/latest/nuget.exe下载最新的 NuGet 可执行文件,并将其放在 PATH 中的某个位置。(您可以将此作为构建前的一个步骤。)
  2. 运行 nuget restore将自动下载所有丢失的软件包。
  3. Run msbuild to build your solution.

另外: 虽然新的和推荐的自动包恢复方法在版本控制中涉及较少的混乱,但是它也使得命令行包恢复成为不可能的,除非您跳过下载和运行 nuget.exe这个额外的环节。有进展吗?

Note that if you are using 团队城市 as a build server, you get a "NuGet Installer" step that you can use to restore all the packages before the build step.

有时,当您在“ package”文件夹(即 “ Packages/EntityFramework.6.0.0/”) 但“ DLL”不在里面(大多数版本控制系统会自动忽略)中有要还原的包的文件夹时,就会发生这种情况。文件)。发生这种情况是因为在 NuGet 尝试恢复每个包之前,它会检查文件夹是否已经存在,所以如果文件夹存在,NuGet 假定“ dll”在其中。因此,如果这是你的问题只是删除文件夹,NuGet 将恢复它正确。

伊恩•坎普(Ian Kemp)给出了答案(顺便说一句,我有一些看法)。.)这只是在他的一个步骤中加入一些肉。

The reason I ended up here was that dev's machines were building fine, but the build server simply wasn't pulling down the packages required (empty packages folder) and therefore the build was failing. Logging onto the build server and manually building the solution worked, however.

为了完成 Ians 3步骤中的第二步(运行 Nuget 恢复) ,您可以创建一个 MSBuild 目标,运行 exec 命令来运行 nuget 恢复命令,如下所示(在本例中,nuget.exe 位于。(而不是在路径上) ,然后可以在构建解决方案之前的 TeamCity 构建步骤(其他可用 CI...)中运行该文件夹

<Target Name="BeforeBuild">
<Exec Command="..\.nuget\nuget restore ..\MySolution.sln"/>
</Target>

根据记录,我已经尝试了“ nuget 安装程序”运行程序类型,但这一步是挂在网络项目(为 DLL 和 Windows 项目工作)

在 VisualStudio2017-当你使用 IDE 编译时-它会下载所有丢失的 uget 包并保存在文件夹“ package”中。

但是在构建机器上,编译是使用 msbuild.exe 完成的,在这种情况下,我下载了 nuget.exe 并保持在 path 中。

During each build process before executing msbuild.exe. It will execute -> nuget.exe restore NAME_OF_SLN_File (if there is only one .SLN file then you can ignore that parameter)

MSBuild15有一个 /t:restore option可以做到这一点。它是与 VisualStudio2017一起提供的。

如果您想使用它,您还必须使用新的 参考资料,这意味着用这样的元素替换 packages.config文件(在 * 中执行此操作)。Csproj) :

<ItemGroup>
<!-- ... -->
<PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" />
<!-- ... -->
</ItemGroup>

如果你右键点击“ References”,就可以自动转换为这种格式(如果你刚刚打开 Visual Studio,重建或打开“ Manage NuGet package for Solution”窗口,它可能就不会出现了,然后它就会开始出现)。

我曾遇到过一个问题,即在使用 devenv.exe 构建 sln 文件的脚本夜间构建中没有包含 nuget 包。

我遵循了 来自微软的建议,关键的一步是在 %AppData%/NuGet中更新 NuGet 配置,使其包含:

<configuration>
<packageRestore>
<add key="automatic" value="True" />
</packageRestore>
</configuration>

你也可以用

Update-Package -reinstall

在 VisualStudio 中的包管理控制台上还原 NuGet 包。