构建期间NuGet软件包文件未被复制到项目内容中

23
我正在使用VS2012专业版和NuGet Package Manager 2.2.31210构建一个MVC4 web应用程序。我的解决方案中有多个项目,它们都共享我使用NuGet安装的各种软件包。其中一个项目是MVC4 web应用程序,在该项目中,我使用了如bootstrap、jquery UI等软件包,这些软件包都是通过NuGet安装的。
当我从存储库克隆整个解决方案的新副本并构建我的MVC4项目时,软件包还原功能似乎在工作:它在解决方案目录下创建了packages目录,并将我期望看到的所有软件包版本都填充到该目录中。然而,内容文件没有被复制到MVC应用程序目录中的适当位置。奇怪的事情是,它确实为内容创建了目录,但未复制内容文件本身。
例如,我正在使用Twitter Bootstrap软件包,该软件包出现在packages/Twitter.Bootstrap.2.2.2中。在MVC项目中,Content目录下会创建一个名为bootstrap的目录(包含css、img和js目录)。但是,没有将css或js文件复制到这些目录中!
有没有人知道我必须说什么神秘的咒语才能使构建复制这些内容文件从NuGet软件包目录中?

1
这似乎是通过此错误跟踪的 http://nuget.codeplex.com/workitem/1239 - Deepak
13
@Deepak,我认为这似乎是一个相当严重的错误。如果NuGet包恢复功能未将文件复制到与包的初始安装时相同的位置,则我认为该功能本质上存在问题。 - AngCaruso
这是有意为之的,如此设计已在此处注明:常见 NuGet 误解:包还原。我在 @FranciscoLopez 的答案存储库中找到了链接。 - oleksa
5个回答

13

这是我们都会遇到的一个常见问题。我创建了一个MSBuild任务NugetContentRestoreTask,可以为您完成此操作。在程序包管理器控制台中运行以下命令:

安装Nuget内容恢复MSBuild目标

    PM> Install-Package MSBuild.NugetContentRestore

唯一剩下的就是从你的BeforeBuild目标中调用它,类似于这样:

项目文件目标

    <Target Name="BeforeBuild">
      <NugetContentRestoreTask SolutionDir="$(SolutionDir)" ProjectDir="$(ProjectDir)" />
    </Target>

你可以查看源代码仓库,并在nuget.org上找到它。

附加内容文件夹

这个 nuget 仅包括默认文件夹 scriptsimagesfontscontent,它不是一个递归目录包含。对于额外的内容子文件夹 - 你必须分配属性 AdditionalFolders

    <Target Name="BeforeBuild">
        <NugetContentRestoreTask SolutionDir="$(SolutionDir)" ProjectDir="$(ProjectDir)" 
              AdditionalFolders="less;sass;common" />
    </Target>

这仍然是相关的,因为NuGet CLI不支持在构建代理上可靠地复制文件的方法 - 只能使用VS IDE工具。 .NET Core仍然不支持使用PackageReference匹配install.ps1packages.config行为。由于没有核心支持,Install.ps1似乎也已被弃用 - SliverNinja - MSFT

11

我找到了解决方法,但它很丑陋。通过在NuGet包管理器控制台中执行以下命令:Update-Package -Reinstall ,所有文件确实被复制到其在Mvc项目 ContentScripts 目录中的正确位置。

不幸的是,这很危险,因为你很可能会得到某些包的错误版本。例如,在我的情况下,当命令执行完成(顺便说一句,这需要相当长的时间)后,我得到了jQuery 1.4.4版本。这太老了,我认为它必须是某个正在更新的其他包的显式依赖项。因此,似乎NuGet实际更新包的顺序很重要(它似乎不会解析所有包的完整依赖树,并从所有依赖关系的并集中仅选择最新版本,这似乎是首选行为)。相反,随着命令的执行,我看到它几次用不同的版本替换jQuery包,然后穿过所有包和它们的依赖项,最终得到了一个非常旧的版本。

类似的方法是对导致问题的每个包显式执行Update-Package -Reinstall 命令,但这非常繁琐且容易出错。

NuGet包还原功能应该产生与手动执行Install-PackageUpdate-Package -Reinstall 命令相同的结果,但实际上并不是这样。


"Update-Package -Reinstall"对我解决了问题(我在Microsoft.WindowsAzure.Storage / WindowsAzure.Storage方面出现了问题,文件CloudAnalyticsClient.cs报错)。 - Nick Niebling
您也可以使用 Update-Package -Reinstall -project YourProject -FileConflictAction OverwriteAll 命令来仅更新特定项目。希望这能帮到您。 - John-Philip

4
我也不喜欢在源代码控制下保存第三方JavaScript文件。这就是为什么我遵循Jeff Handley的建议(http://nuget.codeplex.com/workitem/2094)创建了自己的解决方案。我没有采用可执行文件的方式,而是创建了一个nuget解决方案级别的软件包来解决问题。

http://www.nuget.org/packages/Baseclass.Contrib.Nuget.GitIgnoreContent/

它与git绑定,可以自动更新.gitignore文件。
简短描述:
在git中忽略nuget内容文件:
- 生成 .gitignore 文件中的条目,以从源代码库中排除 nuget 内容文件。 - 在构建之前还原 nuget 内容文件(在 VS 中自动执行,在 PowerShell 脚本中手动执行)。
我撰写了一篇博客文章,介绍如何使用它。 http://www.baseclass.ch/blog/Lists/Beitraege/Post.aspx?ID=9&mobile=0

1
丹尼尔 - 在Windows 10上出现以下问题...<code>无法找到类型[NuGet.VisualStudio.IRepositorySettings]。 位于D:\MOBILEDEV\ionic\Wenzaa\packages\Baseclass.Contrib.Nuget.GitIgnoreContent.0.0.2\tools\Baseclass.Contrib.Nuget.GitIgnoreContent.psm1的第213个字符:
  • ... $componentModel.GetService([NuGet.VisualStudio.IRepositorySettings])
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    • CategoryInfo : InvalidOperation: (NuGet.VisualStudio.IRepositorySettings:TypeName) [], RuntimeException
    • FullyQualifiedErrorId : TypeNotFound
- jessewolfe
看起来这个包已经不再维护了。在Win10上无法与VS2017一起使用... - Emil

3
在Visual Studio 2015更新1中,他们现在支持contentFiles。但是需要注意的是,这只适用于使用project.json的项目。
关于您遇到的问题,有一篇很好的博客文章解释了为什么会出现这种行为:NuGet Package Restore Common Misconceptions

project.json现已弃用- PackageReference现在是管理contentFiles的首选方法 - SliverNinja - MSFT

0

对于我的项目来说,发现只有使用PackageReferences才能使用内容文件:

  1. 通过packages.config引用NuGet包的现有项目
  2. 安装了带有内容文件的NuGet包
  3. 构建项目
  4. 输出目录中没有内容文件

  5. packages.config转换为PackageReferences
  6. 构建项目
  7. 内容文件已复制到输出目录

IDE是Visual Studio 2017。该项目是一个应用程序项目,这意味着它采用旧的csproj格式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接