NuGet自动软件包还原不适用于MSBuild


111

我正在尝试使用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文件夹。
马特·沃德

1
不,我正在从命令行使用最新的MsBuild(msdn.microsoft.com/en-us/library/hh162058.aspx)版本。将Nuget从VS内部更新到2.8-祝您好运。
UserControl 2014年

3
仅MSBuild无法恢复,VS加载项也无法恢复。您需要按照@KMoraz的说明启用软件包还原,然后按Sumeshk的说明显示.nuget文件夹,然后才能恢复软件包。确保您将.nuget签入源代码管理。
Lex Li

Answers:


36

从v3.3.0开始,使用最新的官方NuGet文档进行了更新

包还原方法

NuGet提供了三种使用软件包还原的方法


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


运作方式如下:

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

如果您已安装Nuget 2.7+;请务必选择一种方法>在Visual Studio中管理自动程序包还原。

有两种方法可用:

  1. (Nuget 2.7+):Visual Studio->工具->程序包管理器->程序包管理器设置->启用自动程序包还原
  2. (Nuget 2.6及更低版本)右键单击解决方案,然后单击“为此解决方案启用程序包还原”。


从命令行构建解决方案时,需要进行命令行程序包还原。它是在NuGet的早期版本中引入的,但在NuGet 2.7中得到了改进。

nuget.exe restore contoso.sln

MSBuild集成的程序包还原 方法是原始的程序包还原实现,尽管它在许多情况下仍可以使用,但它不涵盖其他两种方法所解决的全部方案。


63
nuget不再建议这样做。参见文档。docs.nuget.org/docs/workflows/...
欧文约翰逊

@OwenJohnson,该文档没有注明日期,我看不到,也看不出它说现在不建议这样做吗?我在VS2013上,该按钮似乎可以正常工作。我没有提到的问题,“因此,您单击了“启用Nuget软件包还原”,现在您的东西没有建立。解决该问题的步骤很痛苦,但是使用此脚本却不那么痛苦。” github.com/owen2/ AutomaticPackageRestoreMigrationScript也许还有另一个文档对此做进一步解释。
AnneTheAgile 2014年

5
自动软件包还原替代了ms-build集成还原。该文档是有关如何升级的说明。如果您使用msbuild-integrated方法没有问题,则无需执行任何操作。在最简单的情况下,它可以工作,但是如果您有CI服务器,共享的项目引用或某些其他条件,则可能会踩到一些讨厌的地雷,并且提示路径或其他问题不正确。
Owen Johnson

1
使用这个答案并执行docs.nuget.org/consume/package-restore/…上的“删除旧文件”说明“进行迁移” ,我找到了成功。
granadaCoder

NuGet 4和.net标准似乎再次发生了变化。
欧文·约翰逊

239

如果您使用的是Visual Studio 2017或更高版本(随MSBuild 15或更高版本一起提供),并且.csproj文件为PackageReference格式,则最简单的方法是使用新的MSBuild Restore目标


没有人真正回答过最初的问题,即“使用MSBuild从命令行进行构建时,如何使NuGet软件包自动还原?” 答案是:除非您使用“ Enable NuGet package restore”(启用NuGet软件包还原)选项(此参考文献现已弃用)),否则不能这样做(但请参见下文)。如果您尝试在CI服务器上进行自动构建,那么很麻烦。

但是,有一种稍微回旋的方式来获得所需的行为:

  1. https://dist.nuget.org/win-x86-commandline/latest/nuget.exe下载最新的NuGet可执行文件,然后将其放在PATH中。(您可以将其作为预构建步骤。)
  2. nuget restore将自动下载所有缺少的软件包。
  3. 运行msbuild以构建您的解决方案。

顺便说一句:尽管新的推荐的自动软件包还原方法在您的版本控制中减少了混乱,但也使命令行软件包还原成为不可能,除非您跳过了下载和运行的额外工作nuget.exe。进展?


最终得到了类似的解决方案(但放置nuget.exe在/ trunk / ext中)。前进了一步-后退了两步:(
UserControl

40
这应该是正确的答案,而不是标记的答案。
Woland 2015年

确实,这似乎确实有点反常,但是您确实获得了更多功能,可以通过使用命令行来添加特定的nuget包。自动恢复失败时,此解决方案对我有用。
TGarrett

2
我正在使用Jenkins,必须执行此操作,这是调用msbuild之前的简单构建步骤-Windows批处理文件是构建步骤类型,并且:cmd.exe / c“ C:\ Program Files \ nuget \ nuget.exe” restore < RelativePathToSln> .sln-我将SLN的路径作为一种习惯/过程,以防万一找不到sln文件。
Steve Radich-BitShop.com 2015年

1
在Jenkins构建上设置还原时,这种方法对我有用。对我来说,一个重要的关键是NuGet.Config 必须与.SLN文件位于同一目录中。其他配置文件位置(包括在命令行上指定-ConfigFile)的任何组合均不起作用。
Guerry 2015年

56

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

您也可以使用“启用Nuget软件包还原”功能,但是nuget不再推荐这样做,因为它对项目文件进行了侵入性更改,如果在其他解决方案中构建这些项目,则可能会导致问题。


2
如果您的NuGet版本不低于2.7,则需要在使用restore命令之前运行“ nuget update -self”。我的NuGet版本为2.1,并且在更新之前无法识别“恢复”命令。
Teknikaali 2014年

2
“如果在另一个解决方案中构建这些项目,则会引起问题”我还没有遇到任何问题,我们有3个解决方案,每个解决方案都有数十个项目(许多解决方案在多个解决方案之间共享)。也许我很幸运?
纳尔逊·罗瑟梅尔

@NelsonRothermel可能发生的最显着的问题情况是,将由nuget传递的dll引用到外部解决方案的packages文件夹中的项目,当您构建解决方案时,该文件夹可能不可用。
Owen Johnson

2
@OwenJohnson我们为所有解决方案提供了一个公共软件包文件夹,因此这可能就是为什么我们没有遇到问题的原因。
纳尔逊·罗瑟梅尔

17

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

Visual Studio有两种使用包还原的方法:自动包还原和MSBuild集成包还原。“ MSBuild集成软件包还原”在构建过程中还原在某些情况下可能引起问题的软件包。NuGet团队建议使用“自动打包还原” 方法

要使“自动打包还原”工作,需要执行几个步骤:

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

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

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

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

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

  3. 在解决方案中的每个项目文件(.csproj或.vbproj)中,删除引用NuGet.targets文件的行。参考看起来像这样:

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

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

  4. 在Visual Studio菜单中,通过

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

    请启用以下两个选项1)'允许NuGet下载缺少的软件包'2)'在Visual Studio中构建期间自动检查缺少的软件包'

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

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

1
您的步骤之一是删除<导入项目=“ $(MSBuildToolsPath)\ Microsoft.CSharp.targets” />。为什么要这么做?
易卜拉欣(Ibrahim Hashimi)说

3
我认为您误会了模板本身。没有它,您的源文件将根本无法构建。
易卜拉欣(Ibrahim Hashimi)说2014年

3
我认为他的意思是nuget.targets而不是Microsoft.CSharp.targets。
Owen Johnson

2
docs.nuget.org/docs/workflows/…<-这是Ying试图说的官方文档。
Owen Johnson

1
Ying是对的……每个人都忽略了一个事实,那就是,持续集成构建会在构建前事件,获取源代码并阻塞NuGet引用之后创建自己的临时工作区。这是TFS构建自动化的解决方案。
CZahrobsky 2014年

5

MSBuild 15具有执行此操作的/ t:restore选项。它随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
Matthieu

4

伊恩·坎普(Ian Kemp)有答案(顺便说一句。),这只是在他的步骤之一中添加一些肉。

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

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

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

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


1
如果您不断从一组新的代码(CI)进行构建,那么这就是方法。
Jahmic

1
我有点喜欢这种方法,因为它可以保证每个解决方案/项目都依赖于创建它的nuget版本。如果您在一家公司中使用旧版本的项目(使用旧版本的nuget创建)工作,那么在适当的时候,这可能至关重要。开发人员可以维护此类项目,而不必担心整个系统范围的nuget.exe是否会出错,因为每个项目都有自己的nuget.exe“本地风格”。作为最后一个提示,值得注意的是,使用nuget 3.x +,我们可以像这样还原软件包:nuget.exe restore packages.config -PackagesDirectory path \ to \ packages
XDS

1
这种方法的问题在于,您需要编辑任何后续项目文件以添加还原步骤。您可以在TFS2012中添加“ InvokeProcess”活动或在TFS2013构建模板中添加“ NuGetRestore”活动,以在构建服务器上执行此步骤。对于InvokeProcess,请在2012年传入属性“ SourcesDirectory”。在TFS 2013中,只需根据需要填写值。关于如何执行此操作的博客很多。
内维尔

3

请注意,如果将TeamCity用作构建服务器,则会出现“ NuGet安装程序”步骤,可用于在构建步骤之前还原所有软件包。


2

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

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


2
没有.nuget文件夹,从来没有。packages.config项目文件夹中的所有文件都就位。
UserControl 2014年

我认为NuGet.exe和NuGet.targets将在构建应用程序时自动恢复所有丢失的软件包,而您丢失了NuGet.exe和NuGet.targets文件,那是因为它会导致错误
Sumeshk 2014年

无论如何,谢谢-非常感谢您的帮助!
UserControl 2014年

.nu​​get文件夹是Visual Studio生成的文件夹,仅在启用自动程序包还原时显示。在代码存储库中包含nuget.exe很有用,因为您可以在构建中引用它,就像nuget.config一样(特别是如果您需要从多个存储库中获取软件包)。
MytyMyky '16

2

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


1
对于VS 2015和TFS,这可以解决您的问题。问题将是未解决的引用,并且经常出现的问题是未还原nuget软件包,因为该软件包的文件夹已存在于packages文件夹中,但是该软件包尚未完全完全展开。(例如缺少一个应包含.dll的lib文件夹。)删除软件包中软件包的整个文件夹,然后在解决方案级别上单击鼠标右键,然后选择恢复软件包。
格雷格

1

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

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

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

因此,我验证了您在Visual Studio中更改设置时(此处的大多数答案).....以上实际上是更改的内容。另一个“键”是<add key =“ enabled” value =“ False” />。
granadaCoder

0

在Visual Studio 2017中-使用IDE进行编译时-它会下载所有缺少的nuget程序包并保存在“程序包”文件夹中。

但是在生成计算机上,编译是使用msbuild.exe完成的。在这种情况下,我下载了nuget.exe并保存在路径中。

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


0

您也可以使用

Update-Package -reinstall

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


这不是此问题的答案
TS
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.