我对外部和内部包源也有类似的情况,并且在多个解决方案中引用了项目。我今天刚刚使用我们的代码库之一,它似乎正在与开发人员工作站和我们的构建服务器一起使用。下面的过程考虑到了这种情况(尽管在其他地方有通用包文件夹应该不难适应)。
- 代码库
- 项目A
- 项目 B
- 项目 C
- 解决方案
- 解决方案 1
- 解决方案 2
- 解决方案 3
- 包(这是所有解决方案共享的通用包)
使用 Visual Studio 2015 Update 3 从 NuGet 3.5.0.1484 更新答案
这个过程现在比我最初解决这个问题并认为是时候更新它时要容易一些。一般来说,过程是相同的,只是步骤更少。结果是一个解决或提供以下问题的过程:
- 需要提交到源代码控制的所有内容在解决方案中都是可见和跟踪的
- 使用 Visual Studio 中的包管理器安装新包或更新包将使用正确的存储库路径
- 初始配置后,不会对 .csproj 文件进行黑客攻击
- 无需修改开发人员工作站(代码已在签出时构建)
有一些潜在的缺点需要注意(我还没有经历过,YMMV)。请参阅下面的 Benol 的回答和评论。
添加 NuGet.Config
您需要在 \Solutions\ 文件夹的根目录中创建一个 NuGet.Config 文件。确保这是您创建的 UTF-8 编码文件,如果您不确定如何执行此操作,请使用 Visual Studio 的 File->New->File 菜单,然后选择 XML File 模板。将以下内容添加到 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\ 文件夹(您需要先关闭 Visual Studio)。这样可以更轻松地查看 NuGet 将新配置的 \Packages\ 文件夹放在哪里,并确保指向错误 \Packages\ 文件夹的任何链接都将失败,然后可以修复。
在 Visual Studio 中打开您的解决方案并启动 Rebuild All。忽略您将收到的所有构建错误,此时这是预期的。但是,这应该会在构建过程开始时启动 NuGet 包还原功能。验证您的 \Solutions\Packages\ 文件夹是否已在您想要的位置创建。如果没有,请检查您的配置。
现在,对于解决方案中的每个项目,您都需要:
- 右键单击项目并选择卸载项目
- 右键单击项目并选择 Edit your-xxx.csproj
- 找到对 \packages\ 的任何引用并将它们更新到新位置。
- 其中大部分将是 <HintPath> 引用,但不是全部。例如,WebGrease 和 Microsoft.Bcl.Build 将具有需要更新的单独路径设置。
- 保存 .csproj 然后右键单击项目并选择重新加载项目
更新完所有 .csproj 文件后,启动另一个 Rebuild All,您应该不会再遇到有关缺少引用的构建错误。此时您已完成,现在已将 NuGet 配置为使用共享的 Packages 文件夹。
从带有 VStudio 2012 的 NuGet 2.7.1 (2.7.40906.75) 开始
首先要记住的是,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