我有一个类似的情况,涉及到内部和外部包源以及被多个解决方案引用的项目。今天我刚刚在其中一份代码库中做到了这一点,并且似乎在开发人员工作站和构建服务器上都可以工作。下面的过程考虑到了这种情况(尽管将公共包文件夹放在其他位置也不难)。
- 代码库
- 项目A
- 项目B
- 项目C
- 解决方案
- 解决方案1
- 解决方案2
- 解决方案3
- Packages(这是所有解决方案共享的公共文件夹)
使用Visual Studio 2015更新3和NuGet 3.5.0.1484进行更新
现在相比我最初处理此问题时,这个过程要容易些,我认为是时候更新一下了。总的来说,过程是相同的,但步骤更少了。结果是一个可以解决或提供以下功能的工具:
- 需要提交到源代码控制的所有内容在解决方案中都可见并跟踪
- 使用Visual Studio的包管理器安装新包或更新包将使用正确的存储库路径
- 在初始配置之后,不需要修改.csproj文件
- 不需要修改开发人员工作站(代码可在签出时构建)
还有一些潜在的缺点需要注意(我还没有经历过,可能因人而异)。请参阅Benol的答案和下面的评论。
添加NuGet.Config
您将希望在\Solutions\文件夹的根目录中创建一个NuGet.Config文件。确保这是一个UTF-8编码的文件,如果不确定如何操作,请使用Visual Studio的“文件”->“新建”->“文件”菜单,然后选择XML文件模板。在NuGet.Config中添加以下内容:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="repositoryPath" value="$\..\Packages" />
</config>
</configuration>
对于 repositoryPath 设置,可以使用 $ 符号指定绝对路径或相对路径(建议使用相对路径)。$ 符号是基于 NuGet.Config 的位置(实际上 $ 符号相对于 NuGet.Config 位置的一级目录下)。因此,如果我有 \Solutions\NuGet.Config 并且我想要 \Solutions\Packages,我需要将 $\..\Packages 指定为值。
接下来,您需要在解决方案中添加一个名为 "NuGet" 的解决方案文件夹(右键单击解决方案,选择-> 新建解决方案文件夹)。 解决方案文件夹是仅存在于 Visual Studio 解决方案中而不会在驱动器上创建实际文件夹的虚拟文件夹(您可以从任何地方引用文件)。右键单击“NuGet”解决方案文件夹,然后选择添加->现有项目,选择\Solutions\NuGet.Config。
我们这样做的原因是为了使其在解决方案中可见,并应有助于确保它被正确提交到源代码控制。您可能需要为与共享项目参与的代码库中的每个解决方案执行此步骤。
通过将 NuGet.Config 文件放置在任何 .sln 文件之上的 \Solutions\ 中,我们利用 NuGet 将从“当前工作目录”向上递归导航文件夹结构,寻找要使用的 NuGet.Config 文件的事实。 “当前工作目录”在这里有几种不同的含义,其中一种是 NuGet.exe 的执行路径,另一种是 .sln 文件的位置。
切换您的 packages 文件夹
首先,我强烈建议您浏览每个解决方案文件夹并删除任何存在的 \Packages\ 文件夹(您需要先关闭 Visual Studio)。这样可以更容易地看到 NuGet 将您新配置的 \Packages\ 文件夹放置在哪里,并确保任何链接到错误 \Packages\ 文件夹的链接将失败,然后可以进行修复。
在 Visual Studio 中打开您的解决方案并启动 Rebuild All。您将收到所有构建错误,但这在此时是预期的。这应该会在构建过程开始时启动 NuGet 包恢复功能。验证您的 \Solutions\Packages\ 文件夹是否已创建在所需位置。如果没有,请重新查看您的配置。
现在,对于您解决方案中的每个项目,您将需要:
- 右键单击该项目并选择 Unload Project
- 右键单击该项目并选择编辑 your-xxx.csproj
- 查找任何引用 \packages\ 的内容,并将其更新为新位置。
- 大多数这些将是 <HintPath> 引用,但不是所有引用。例如,WebGrease 和 Microsoft.Bcl.Build 将具有需要更新的单独路径设置。
- 保存 .csproj,然后右键单击该项目并选择 Reload Project
所有的.csproj文件都更新完毕后,再次进行Rebuild All操作,就不会再出现关于缺少引用的构建错误。此时你已经完成了,并且现在已经配置好NuGet以使用共享的Packages文件夹。
NuGet 2.7.1(2.7.40906.75)及Visual Studio 2012起
首先要记住的是,nuget.config并不能控制nuget包系统中的所有路径设置。这一点特别令人困惑。具体来说,问题在于msbuild和Visual Studio(调用msbuild)没有使用nuget.config中的路径,而是在nuget.targets文件中进行了覆盖。
环境准备
首先,我会遍历你解决方案的文件夹,并删除所有已存在的\packages\文件夹。这将有助于确保所有软件包都能正确地安装到指定文件夹,并帮助发现解决方案中的任何错误路径引用。接下来,确保你已经安装了最新版本的NuGet Visual Studio扩展程序。还要确保你已经在每个解决方案中安装了最新版本的nuget.exe。打开一个命令提示符并进入每个$(SolutionDir)\.nuget\文件夹,执行以下命令:
nuget update -self
为NuGet设置常见的包文件夹路径
打开每个 $(SolutionDir)\.nuget\NuGet.Config 文件,并在 <configuration> 部分中添加以下内容:
<config>
<add key="repositorypath" value="$\..\..\..\Packages" />
</config>
注意:您可以使用绝对路径或相对路径。请记住,如果您正在使用带有$的相对路径,则它是相对于NuGet.Config位置的下一级(认为这是一个错误)。
为MSBuild和Visual Studio设置常见软件包文件夹路径
打开每个$(SolutionDir)\ .nuget\NuGet.targets文件并修改以下部分(请注意,对于非Windows平台,下面还有另一节):
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
<!-- Windows specific commands -->
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
<PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
<PackagesDir>$([System.IO.Path]::Combine($(SolutionDir), "packages"))</PackagesDir>
</PropertyGroup>
将PackagesDir更新为
<PackagesDir>$([System.IO.Path]::GetFullPath("$(SolutionDir)\..\Packages"))</PackagesDir>
注意:GetFullPath将相对路径解析为绝对路径。
将所有NuGet包还原到公共文件夹
打开命令提示符并转到每个$(SolutionDir)\ .nuget,并执行以下命令:
nuget restore ..\YourSolution.sln
此时,您应该在公共位置中拥有一个单独的 \packages\ 文件夹,并且不存在于任何解决方案文件夹中。如果没有,请验证您的路径。
修复项目引用
在文本编辑器中打开每个 .csproj 文件并查找对 \packages 的引用,并将其更新为正确的路径。大多数情况下,这些引用将是 <HintPath> 引用,但不是所有引用都是如此。例如,WebGrease 和 Microsoft.Bcl.Build 将具有需要更新的单独路径设置。
构建您的解决方案
在 Visual Studio 中打开您的解决方案并启动构建。如果它抱怨需要恢复缺少的包,请不要假设该包已经丢失并需要进行还原(错误可能会误导)。它可能是您的某个 .csproj 文件中的错误路径。请先检查此问题然后再还原包。
遇到有关缺少包的构建错误?
如果您已经验证了 .csproj 文件中的路径是否正确,则有两种尝试方法。如果这是从源代码控制更新代码的结果,那么您可以尝试签出一个干净的副本,然后构建该副本。这对我们的其中一位开发者起作用了,我认为是 .suo 文件中的某个工件或类似物。另一个选择是在相关解决方案的 .nuget 文件夹中使用命令行手动强制还原包:
nuget restore ..\YourSolution.sln
$
。关于 NuGet.Config 文件的问题,答案在这里。它首先查找 .nuget,然后查找所有父目录,然后在您的 AppData 中查找“全局”文件:然后以相反的顺序应用它们(无论那意味着什么)。 - Benjol