Jenkins不能使用新的MSBuild恢复目标还原NuGet包

49
我们有一个基于.NET全框架的WPF应用程序,我们将其从.net 4.6.2移动到了4.7.1,同时在csproj文件中改为使用PackageReference而不是packages.config。在开发机上构建似乎没问题,包被下载并还原了,但是当我们在Windows Server 2012构建服务器上使用Jenkins构建时,NuGet包似乎没有正确还原。我们正在使用MSBuild v15.5和最新的"msbuild /restore"命令在构建时还原包。注意:使用以前的"nuget restore"调用方式确实可行,但我们应该能够现在使用msbuild /restore。包还原过程似乎在查看正确的NuGet服务器,并且似乎在没有错误的情况下完成了还原(这是在Jenkins上编译的测试解决方案,以隔离问题)。
Restore:
  Restoring packages for c:\Jenkins\workspace\Test\ConsoleApp1\ConsoleApp1.csproj...
  Committing restore...
  Generating MSBuild file c:\Jenkins\workspace\Test\ConsoleApp1\obj\ConsoleApp1.csproj.nuget.g.props.
  Generating MSBuild file c:\Jenkins\workspace\Test\ConsoleApp1\obj\ConsoleApp1.csproj.nuget.g.targets.
  Writing lock file to disk. Path: c:\Jenkins\workspace\Test\ConsoleApp1\obj\project.assets.json
  Restore completed in 577.05 ms for c:\Jenkins\workspace\Test\ConsoleApp1\ConsoleApp1.csproj.

  NuGet Config files used:
      c:\Jenkins\workspace\Test\NuGet.Config
      C:\Windows\system32\config\systemprofile\AppData\Roaming\NuGet\NuGet.Config

  Feeds used:
      http://devbuild/NuGetHost/nuget
      https://api.nuget.org/v3/index.json
Done Building Project "c:\Jenkins\workspace\Test\ConsoleApp1.sln" (Restore target(s)).

但是当msbuild编译代码时,我们会遇到以下错误,看起来NuGet还没有被下载:

CSC : error CS0006: Metadata file 'C:\Windows\system32\config\systemprofile\.nuget\packages\log4net\2.0.8\lib\net45-full\log4net.dll' 
could not be found [c:\Jenkins\workspace\Test\ConsoleApp1\ConsoleApp1.csproj]

你有任何想法为什么nuget包无法还原吗?

5个回答

73

经过多个小时的搜索和筛选NuGet问题帖子,并过滤掉.net core噪音,我找到了解决方法!

根据一些提出的NuGet和msbuildmsbuild问题,当在Windows Server 2012的本地系统账户下使用NuGet(或msbuild /restore)进行还原时,NuGet使用的文件夹无法访问或是不同的文件夹,因为运行的进程是32位还是64位,所以无法将nugets下载到该本地缓存文件夹中。

这个文件夹在编译时msbuild想要查看似乎是C:\Windows\system32\config\systemprofile\.nuget\packages

我们的解决方法是使用系统全局环境变量NUGET_PACKAGES来设置NuGet包缓存文件夹,指向另一个可访问的文件夹,例如C:\NugetPackageCache。

NUGET_PACKAGES=C:\NugetPackageCache

通过设置构建环境->向构建过程注入环境变量->属性内容,您也可以针对每个Jenkins项目进行设置:

NUGET_PACKAGES=C:/NugetPackageCache

根据这篇NuGet问题帖子提出的另一个潜在解决方法是将环境变量设置为msbuild正在寻找nugets的文件夹,即

NUGET_PACKAGES=C:\Windows\system32\config\systemprofile\.nuget\packages

注意:环境变量在 NuGet 中具有优先级。似乎他们还没有更新NuGet文档提到它的优先级注意:我们使用EnvInject Jenkins插件来注入/设置环境变量,看起来像这样: Jenkins plugin with environment variables

1
@mips 请问你能否在Jenkins配置中添加一个屏幕,展示它的外观?我遇到了同样的问题。 - rpmansion
我在使用TeamCity时也遇到了同样的问题,这个解决方案对我也起作用了。谢谢! - Logerfo
我考虑将目录相对于构建目录进行设置,否则,你可能会得到共享目录的作业,这可能是可以接受的,但也会使作业相互依赖。 - bpeikes
我已经放弃了,直到我看到了这篇文章。我通过添加以下内容解决了这个问题:environment{ NUGET_PACKAGES="${env.WORKSPACE}/mynugetpackagecache" } - Sau001
我在 Jenkins 安装中遇到了问题。它以前是在域用户帐户下运行的,当我重新安装时,决定使用 LocalSystem 进行安装。将其添加为系统级环境变量,重启 Jenkins,一切都正常。 - Paul_LayLow
尝试了其他答案和评论中提到的所有方法,但在我的情况下仍然没有帮助:https://dev59.com/pMXsa4cB1Zd3GeqPb11Q - SH4NNY1

11

对于我们而言,问题确实涉及位数!

具体问题是MSBuild实际上在以下目录中寻找NuGet软件包:

C:\Windows\SysWOW64\config\systemprofile\.nuget\packages

即使日志实际上说:

C:\Windows\System32\config\systemprofile\.nuget\packages

由于在64位平台上运行的32位进程中调用了msbuild时,它查找System32目录实际上是在查找SysWOW64目录。

这是通过文件系统重定向完成的。

对我们而言,解决方案就是简单地调用位于以下位置的64位版本的MSBuild:

C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\amd64\MSBuild.exe

请注意路径中的amd64


8
我们最近在一项.NET Framework 项目中遇到了一个非常相似但略有不同的情况,将其都转换为4.7.2,并使用<PackageReference>而不是packages.config,构建基于Windows的Jenkins服务器,其中服务以Local System运行。 在我们的情况下,我们发现nuget restore根本没有查看我们的私人MyGet源,因此没有从该源安装我们自己的软件包,这导致构建失败。 它在nuget restore命令后未显示在“使用的来源”列表中。
mips在这里的回答(以及链接到那里的NuGet问题)的启发,我发现问题是尽管将C:\Windows\system32\config\systemprofile\AppData\Roaming\NuGet\NuGet.config列为配置源(确实是我们的MyGet源配置的位置),但实际上它使用的是C:\Windows\SysWOW64\config\systemprofile\AppData\Roaming\NuGet\NuGet.config。 我能够通过将NuGet.config文件从system32位置复制到SysWOW64位置来解决问题。
没有必要配置和注入NUGET_PACKAGES环境变量。

1
哇!这正是我整天与Jenkins和Nuget的包引用问题。系统配置文件存在两次,真是太邪恶了。 - BlueM

1
您可以在 Nuget.Config 中设置不同的程序包路径:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
  </packageSources>
  <config>
    <add key="repositoryPath" value="C:\NugetPackages" />
    <add key="globalPackagesFolder" value="C:\NugetPackages" />
  </config>
</configuration>

0
你可以使用类似下面的方法,假设TerminalHostBroker是包含一些需要恢复的NuGet包的解决方案:
NuGet restore R:\Tools\TerminalHostBroker\TerminalHostBroker.sln -NonInteractive -NoCache -ConfigFile C:\Installers\NuGet.Config

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