NuGet 自动包还原不适用于 MSBuild

Posted

技术标签:

【中文标题】NuGet 自动包还原不适用于 MSBuild【英文标题】:NuGet auto package restore does not work with MSBuild 【发布时间】:2014-04-13 13:38:40 【问题描述】:

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

“您是否缺少 using 指令或程序集引用?”

NuGet Manager 是 2.7(我在 Visual Studio 2013 中看到了这个关于框)。我什至尝试传递 EnableNuGetPackageRestore=true 参数 - 不走运。我错过了什么?

【问题讨论】:

您是否在 Visual Studio 中构建解决方案?包还原部分的包管理器设置中的所有内容都打勾了吗?如果您在 Visual Studio 中构建并使用 NuGet 2.7 或更高版本,则不需要 .nuget 文件夹。 不,我正在从命令行使用最新的 MsBuild (msdn.microsoft.com/en-us/library/hh162058.aspx) 版本。将 VS 中的 Nuget 更新到 2.8 - 不走运。 单独的 MSBuild 不会恢复,VS 插件也不会。您需要像@KMoraz 所说的那样启用包恢复,然后像 Sumeshk 所说的那样,出现 .nuget 文件夹并且可以恢复包。确保将 .nuget 签入源代码管理。 【参考方案1】:

如果您使用的是 MSBuild 15 或更高版本附带的 Visual Studio 2017 或更高版本,并且您的 .csproj 文件位于 new PackageReference format,最简单的方法是 use the new MSBuild Restore target。 p>


没有人真正回答过最初的问题,即“在使用 MSBuild 从命令行构建时,如何让 NuGet 包自动恢复?”答案是:除非您使用“启用 NuGet 包还原”选项(现在根据 this reference 已弃用),否则您不能(但请参见下文)。如果你正在尝试做例如在 CI 服务器上自动构建,这很糟糕。

但是有一个稍微迂回的方法来获得所需的行为:

    从https://dist.nuget.org/win-x86-commandline/latest/nuget.exe 下载最新的 NuGet 可执行文件并将其放置在 PATH 中的某个位置。 (您可以将此作为预构建步骤。) 运行nuget restore,它将自动下载所有丢失的包。 运行 msbuild 以构建您的解决方案。

除此之外:虽然新的和推荐的自动包恢复方法在版本控制中减少了混乱,但它也使命令行包恢复变得不可能,除非你跳过下载和运行nuget.exe 的额外环节。进展吗?

【讨论】:

最终得到了类似的解决方案(但将 nuget.exe 放置在 /trunk/ext 中)。前进一步 - 后退两步 :( 这应该是正确的答案,而不是标记的答案。 归根结底,这确实看起来有点违反直觉,但是您确实可以获得更多功能来使用命令行添加特定的 nuget 包。当自动恢复失败时,此解决方案对我有用。 我使用 Jenkins 并且必须这样做,这是调用 msbuild 之前的一个简单构建步骤 - Windows 批处理文件是构建步骤类型,并且:cmd.exe /c "C:\Program Files\ nuget\nuget.exe" restore .sln - 我将 SLN 的路径作为一种习惯/过程,以防万一它没有找到 sln 文件。 在 Jenkins 构建上设置恢复时,这种方法对我有用。对我来说,一个重要的关键是 NuGet.Config 必须 与我的 .SLN 文件位于同一目录中。其他配置文件位置的组合,包括在命令行上指定 -ConfigFile 都不起作用。【参考方案2】:

Nuget 的自动包还原是 Visual Studio 的一项功能(从 2013 年开始),而不是 MSBuild。如果您想从命令行恢复软件包,您必须运行 nuget.exe restore

您也可以使用启用 Nuget 包还原功能,但 nuget 人员不再建议这样做,因为它会对项目文件进行侵入性更改,并且如果您在另一个解决方案中构建这些项目可能会导致问题。

【讨论】:

如果您的 NuGet 版本不是至少 2.7,您需要在使用 restore-command 之前运行“nuget update -self”。我的 NuGet 是 2.1 版,更新前无法识别“恢复”命令。 “如果你在另一个解决方案中构建这些项目会导致问题” 我还没有遇到任何问题,我们有 3 个解决方案,每个解决方案都有数十个项目(许多项目在解决方案之间共享)。也许我很幸运? @NelsonRothermel 可能发生的最明显的问题情况是项目将 nuget 交付的 dll 引用到外部解决方案的包文件夹中,当您构建解决方案时可能不可用。 @OwenJohnson 我们为所有解决方案提供了一个通用包文件夹,所以这可能就是我们没有遇到问题的原因。【参考方案3】:

更新了自 v3.3.0 起的最新官方 NuGet 文档

包恢复方法

NuGet 提供了三种使用 package restore 的方法。


Automatic Package Restore 是 NuGet 团队推荐的在 Visual Studio 中进行包还原的方法,它是在 NuGet 2.7 中引入的。 从 NuGet 2.7 开始,NuGet Visual Studio 扩展集成到 Visual Studio 的生成事件中,并在生成开始时恢复丢失的包。此功能默认启用,但如果需要,开发人员可以选择退出。


它是这样工作的:

    在项目或解决方案构建时,Visual Studio 会引发一个事件, 在解决方案中开始构建。 NuGet 响应此事件 并检查解决方案中包含的 packages.config 文件。 对于找到的每个 packages.config 文件,都会枚举其包并 检查解决方案的包文件夹中是否存在。 任何丢失的包都是从用户配置(并启用)的包源中下载的,遵循包源的顺序。 下载软件包后,它们会解压缩到解决方案的 包文件夹。

如果您安装了 Nuget 2.7+;选择一种方法来管理 Visual Studio 中的自动包还原非常重要。

有两种方法:

    (Nuget 2.7+):Visual Studio -> 工具 -> 包管理器 -> 包 管理器设置 -> 启用自动包恢复 (Nuget 2.6 及更低版本)右键单击解决方案并单击“启用包 恢复此解决方案”。


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

nuget.exe restore contoso.sln

The MSBuild-integrated package restore 方法是原始的包还原实现,尽管它 在许多场景中继续工作,它不涵盖全套 其他两种方法解决的场景。

【讨论】:

nuget 不再推荐这个。请参阅文档。 docs.nuget.org/docs/workflows/… @OwenJohnson,我可以看到该文档没有过时,我不明白它怎么说现在不推荐?我在 VS2013 上,那个按钮似乎工作正常。我没有提到问题,“所以,您单击了“启用 Nuget 包还原”,现在您的东西没有构建。修复它的步骤很痛苦,但这个脚本不那么痛苦。“github.com/owen2/AutomaticPackageRestoreMigrationScript也许有另一个文档进一步解释了这一点。 自动包还原取代了 ms-build 集成还原。该文档是有关如何升级的说明。如果您对 msbuild-integrated 方法没有问题,则无需执行任何操作。在最简单的情况下,它可以工作,但如果您有 CI 服务器、共享项目引用或其他一些情况,您可能会踩到一些令人讨厌的地雷,并出现不正确的提示路径或其他问题。 使用这个答案并在docs.nuget.org/consume/package-restore/… 执行“删除旧东西”说明“执行迁移”,我能够找到成功。 看起来随着 NuGet 4 和 .net 标准再次发生变化。【参考方案4】:

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

Visual Studio 有两种使用包还原的方法:自动包还原和 MSBuild 集成包还原。 “MSBuild-Integrated Package Restore”在构建过程中恢复包,这可能会在某些情况下导致问题。 NuGet 团队的“自动包还原”是the recommended approach。

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

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

    如果您使用 TFS,请在解决方案的 .nuget 文件夹中删除 NuGet.exe 和 NuGet.targes 文件。然后编辑 NuGet.Config 以不签入 NuGet 包:

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

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

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

    在解决方案的每个项目文件(.csproj 或 .vbproj)中,删除引用 NuGet.targets 文件的行。参考如下所示:

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

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

    在 Visual Studio 菜单中,通过

    工具 -> 选项 -> 包管理器 -> 常规或 工具 -> NuGet 包管理器 -> 包管理器设置

    请启用以下两个选项 1) '允许 NuGet 下载丢失的包' 2) '在 Visual Studio 构建过程中自动检查丢失的包'

    通过以下步骤测试您的包还原配置

    保存解决方案并关闭 Visual Studio 删除解决方案的包文件夹 启动 Visual Studio,打开您的解决方案并重新构建它。

【讨论】:

您的步骤之一是删除 。你为什么要这么做? 我认为您弄错了模板本身。没有它,您的源文件将根本无法构建。 我认为他的意思是 nuget.targets 而不是 Microsoft.CSharp.targets。 docs.nuget.org/docs/workflows/… Ying 是对的......每个人都忽略了一个事实,即持续集成构建在预构建事件之后创建自己的临时工作区,获取源,然后阻塞 NuGet 引用。这是 TFS 构建自动化的修复。【参考方案5】:

MSBuild 15 有一个 /t:restore option 可以做到这一点。它带有 Visual Studio 2017。

如果你想使用这个,你还必须使用新的PackageReference,这意味着用这样的元素替换packages.config文件(在*.csproj中这样做):

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

如果您右键单击“参考”,则会自动迁移到此格式(如果您刚刚打开 Visual Studio,它可能不会显示,重新构建或打开“管理用于解决方案的 NuGet 包”窗口,它将开始出现)。

【讨论】:

您必须考虑到 msbuild 的 restore 选项与 nuget restore 的细微差别 - 例如参见 github.com/NuGet/Home/issues/7651#issuecomment-500842049。【参考方案6】:

请注意,如果您使用 TeamCity 作为构建服务器,您将获得一个“NuGet 安装程序”步骤,您可以使用该步骤在构建步骤之前恢复所有包。

【讨论】:

【参考方案7】:

Ian Kemp 给出了答案(顺便说一句……),这是在他的一个步骤中简单地添加一些肉。

我最终来到这里的原因是开发人员的机器构建良好,但构建服务器根本没有拉下所需的包(空包文件夹),因此构建失败。但是,登录到构建服务器并手动构建解决方案是可行的。

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

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

作为记录,我已经尝试过“nuget 安装程序”运行器类型,但此步骤挂在 Web 项目上(适用于 DLL 和 Windows 项目)

【讨论】:

如果您不断地从一组新的代码 (CI) 构建,这就是要走的路。 我有点喜欢这种方法,因为它保证每个解决方案/项目都依赖于创建它的 nuget 版本。如果您在一家拥有使用旧版本 nuget 创建的旧项目的公司工作,这将在适当的时候证明是至关重要的。开发人员可以维护此类项目,而不必担心系统范围的 nuget.exe 是否会破坏,因为每个项目都有自己的“本地风味”的 nuget.exe。作为最后一个提示,值得注意的是,使用 nuget 3.x+ 我们可以像这样恢复包: nuget.exe restore packages.config -PackagesDirectory path\to\packages 这种方法的问题是您需要编辑任何后续项目文件以添加恢复步骤。您可以在 TFS2012 中添加“InvokeProcess”活动或在 TFS2013 构建模板中添加“NuGetRestore”活动,以便在构建服务器上执行此步骤。对于 InvokeProcess,在 2012 中传入属性“SourcesDirectory”。在 TFS 2013 中,只需根据需要填写值即可。有很多关于如何做到这一点的博客。【参考方案8】:

项目中有一个 packages.config 文件,它包含包的详细信息。

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

【讨论】:

没有.nuget 文件夹,从来没有。项目文件夹中的所有packages.config 文件均已就位。 我认为 NuGet.exe 和 NuGet.targets 会在构建应用程序时自动恢复所有丢失的包,而你丢失了 NuGet.exe 和 NuGet.targets 文件,这会导致错误 还是谢谢你-我很感激任何帮助! .nuget 文件夹是 Visual Studio 生成的文件夹,仅当您启用自动包还原时才会出现。在代码仓库中包含 nuget.exe 很有用,因为您可以在构建中引用它,nuget.config 也是如此(特别是如果您需要从多个仓库获取包)。【参考方案9】:

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

【讨论】:

对于 VS 2015 和 TFS,这将解决您的问题。问题将是未解决的引用,并且通常问题是未还原 nuget 包,因为该包的文件夹已存在于 packages 文件夹中,但该包尚未完全正确展开。 (例如缺少一个应该包含.dll的lib文件夹。)在packages中删除package的整个文件夹,然后在解决方案级别右键单击并选择restore packages。【参考方案10】:

我遇到了一个问题,即使用 devenv.exe 构建 sln 文件的脚本化夜间构建中未包含 nuget 包。

我遵循advice from Microsoft,关键步骤是更新%AppData%/NuGet 中的NuGet 配置,使其包含:

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

【讨论】:

所以我验证了当您更改 Visual Studio 中的设置时(这里的大部分答案)......实际上上面的内容发生了变化。另一个“关键”是 。【参考方案11】:

在 Visual Studio 2017 中 - 当您使用 IDE 编译时 - 它将下载所有缺少的 nuget 包并保存在“packages”文件夹中。

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

在执行 msbuild.exe 之前的每个构建过程中。它将执行 -> nuget.exe restore NAME_OF_SLN_File (如果只有一个 .SLN 文件,则可以忽略该参数)

【讨论】:

【参考方案12】:

你也可以使用

Update-Package -reinstall

在 Visual Studio 的包管理控制台上还原 NuGet 包。

【讨论】:

这不是这个问题的答案

以上是关于NuGet 自动包还原不适用于 MSBuild的主要内容,如果未能解决你的问题,请参考以下文章

NuGet自动更新特定包

NuGet 包还原 + NuGet 源设置

从解决方案中删除 nuget 包还原

1分钟解决VS每次运行都显示“正在还原nuget程序包”问题

VS一直停留在“正在还原nuget程序包”

NuGet 还原无法看到未安装包