当一些项目包含在多个解决方案中时,为所有解决方案设置一个通用的 nuget 软件包文件夹

我一直在使用 NuGet 从外部和内部包源检索包,这非常方便。但是我已经意识到每个解决方案的包都是默认存储的,当一些具有 NuGet 引用的项目包含在多个解决方案中时,这是非常令人沮丧的。然后将引用更改为其他解决方案包文件夹,这些解决方案包文件夹实际上可能对其他开发人员或生成计算机不可用。

我已经看到,在 NuGet 的发行版2.1中,有一些方法可以指出一个公共的包位置(可能在项目根级,我们使用 TFS 源代码控制) ,请参阅 释放通知书。我正在使用 NuGet v2.7

但是我尝试添加 nuget.config 文件,但是没有看到任何效果。包仍然存储在解决方案文件夹中。我错过了什么吗? 要添加到 nuget.config 文件的 xml 节点似乎有不同的结构,具体取决于回答这个问题的人: 施瓦茨在 另一个堆栈溢出线程节目中建议:

<settings>
<repositoryPath>..\..\[relative or absolute path]</repositoryPath>
</settings>

NuGet 2.1的发布说明(见上面的链接)提出了这种格式:

<configuration>
<config>
<add key="repositoryPath" value="..\..\[relative or absolute path]" />
</config>
</configuration>

我不知道这些中的哪一个,或者任何一个,或者两个最终都会起作用。我在解决方案级别都试过了。 Config 文件是否可以放在 TFS 项目根目录级别,或者必须放在解决方案目录中?NuGet 似乎是按照一定的顺序从这些文件中读取和应用设置的,为什么将它们添加到几个级别是有意义的,其中解决方案级别的 NuGet.config 文件将覆盖 TFS 项目根级别的设置。能澄清一下吗?

我需要删除所有已安装的软件包之前,这些引用将工作? 我希望有人能够提供一个逐步指导,从解决方案特定的 nuget 使用转移到一个公共的包文件夹,在那里属于多个解决方案的项目可以找到他们所需的 nuget 包。

101752 次浏览

我有一个类似的情况与外部和内部的包来源与项目中引用的多个解决方案。我刚刚得到这个工作与我们的一个代码库今天,它似乎与开发人员工作站和我们的构建服务器工作。下面的过程考虑到了这个场景(尽管在其他地方使用通用的包文件夹应该不难)。

  • 代码库
    • 项目 A
    • B 计划
    • C 计划
    • 解决方案
      • 解决方案1
      • 解决方案2
      • 解决方案3
      • 包(这是所有解决方案共享的公共包)

使用 Visual Studio 2015 Update 3更新了 NuGet 3.5.0.1484的答案

现在这个过程比我最初处理这个问题并认为是时候更新这个问题时要容易一些。一般来说,过程是相同的,只是步骤较少。其结果是一个解决或提供以下问题的过程:

  • 需要提交给源代码控制的所有内容都可以在解决方案中看到并跟踪
  • 在 VisualStudio 中使用 PackageManager 安装新包或更新包将使用正确的存储库路径
  • 在初始配置之后,不要修改. csproj 文件
  • 没有开发人员工作站的修改(代码在检出时已经构建好)

有一些潜在的不利因素需要注意(我还没有经历过,YMMV)。请参阅下面的 Benol 的答案和评论。

添加 NuGet.Config

您将希望创建一个 NuGet。“解决方案”文件夹根目录中的配置文件。确保创建的是 UTF-8编码的文件,如果不确定如何创建,请使用 Visual Studio 的 File-> New-> File 菜单,然后选择 XML File 模板。添加到 NuGet。配置如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="repositoryPath" value="$\..\Packages" />
</config>
</configuration>

对于 RepositoryPath 设置,可以使用 $Token 指定绝对路径或相对路径(推荐)。$token 基于 NuGet 的位置。Config 被定位($token 实际上是相对于 NuGet 的位置 下面一层的。配置)。所以,如果我有解决方案 NuGet。配置和我想解决方案包,我需要指定 $。.包作为值。

接下来,您需要向您的解决方案添加一个名为“ NuGet”的解决方案文件夹(右键单击您的解决方案,添加-> 新建解决方案文件夹)。“解决方案文件夹”是仅存在于 VisualStudio 解决方案中的虚拟文件夹,不会在驱动器上创建实际文件夹(并且可以从任何地方引用文件)。右键单击“ NuGet”解决方案文件夹,然后添加-> 现有项目,并选择 Solutions NuGet。配置。

我们这样做的原因是为了使它在解决方案中可见,并且应该有助于确保它正确地提交到源代码控制中。您可能希望为参与共享项目的代码库中的每个解决方案执行此步骤。

通过放置 NuGet。解决方案中的配置文件。我们正在利用这样一个事实,即 NuGet 将递归导航文件夹结构从“当前工作目录”向上寻找一个 NuGet。要使用的配置文件。“当前工作目录”在这里指的是几个不同的东西,一个是 NuGet.exe 的执行路径,另一个是。档案。

切换包文件夹

首先,我强烈建议您检查每个解决方案文件夹并删除所有现有的 Packages 文件夹(首先需要关闭 VisualStudio)。这样可以更容易地看到 NuGet 将新配置的 Packages 文件夹放在哪里,并确保任何链接到错误的 Packages 文件夹将失败,然后可以修复。

在 VisualStudio 中打开解决方案并启动“全部重新生成”。忽略您将收到的所有构建错误,这是此时所期望的。然而,这应该在构建过程开始时启动 NuGet 包恢复特性。验证您的“解决方案包”文件夹是否已在所需的现场创建。如果没有,请检查您的配置。

现在,对于解决方案中的每个项目,您需要:

  1. 右键单击该项目并选择“卸载项目”
  2. 右键单击该项目并选择 Edit your-xxx. csproj
  3. 查找对包的任何引用并将它们更新到新位置。
    • 其中大部分是 < HintPath > 引用,但不是全部。例如,WebGrease 和微软。Bcl.构建将有需要更新的单独路径设置。
  4. 保存. csproj,然后右键单击项目并选择 ReloadProject

曾经你所有的。Csproj 文件已经更新,启动另一个全部重建,您应该没有更多的构建错误关于缺少引用。此时,您已经完成了任务,现在已经将 NuGet 配置为使用共享 Packages 文件夹。

从 NuGet 2.7.1(2.7.40906.75)到 VStudio 2012

首先要记住的是,nuget.config 并不控制 nuget 包系统中的所有路径设置。这个问题尤其令人困惑。具体来说,问题在于 msbuild 和 Visual Studio (调用 msbuild)不使用 nuget.config 中的路径,而是在 nuget.target 文件中重写它。

环境准备

首先,我将浏览您的解决方案的文件夹,并删除所有包文件夹的存在。这将有助于确保所有软件包都安装在正确的文件夹中,并有助于发现解决方案中的任何错误路径引用。 接下来,我将确保您安装了最新的 nuget Visual Studio 扩展。 我还要确保在每个解决方案中都安装了最新的 nuget.exe。打开命令提示符并进入每个 $(SolutionDir)。Nuget 文件夹并执行以下命令:

nuget update -self

为 NuGet 设置公共包文件夹路径

打开每个 $(SolutionDir) . NuGet.Config 并在 < configuration > 部分中添加以下内容:

<config>
<add key="repositorypath" value="$\..\..\..\Packages" />
</config>

注意: 可以使用绝对路径或相对路径。请记住,如果您使用的是一个相对路径与 $,它是相对于 下面一层的位置 NuGet。配置(相信这是一个错误)。

为 MSBuild 和 VisualStudio 设置通用包文件夹路径

打开每个 $(SolutionDir) . nuget.target 并修改以下部分(注意,对于非 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>$([System.IO.Path]::GetFullPath("$(SolutionDir)\..\Packages"))</PackagesDir>

注意: GetFullPath 将把相对路径解析为绝对路径。

将所有 nuget 包还原到通用文件夹中

打开命令提示符并转到每个 $(SolutionDir) . nuget 并执行以下命令:

nuget restore ..\YourSolution.sln

此时,您的公共位置中应该只有一个包文件夹,而在任何解决方案文件夹中都没有包文件夹。如果没有,那么验证您的路径。

修改项目参考文献

打开每一个。文本编辑器中的 csproj 文件,并找到任何对包的引用,并将它们更新到正确的路径。其中大部分是 < HintPath > 引用,但不是全部。例如,WebGrease 和微软。Bcl.构建将有需要更新的单独路径设置。

构建解决方案

在 VisualStudio 中打开解决方案并启动生成。如果它抱怨丢失了需要还原的包,不要假设包丢失了并且需要还原(错误可能会误导)。这可能是你的一条不好的路。Csproj 文件。在恢复软件包之前先检查一下。

是否有关于丢失包的构建错误?

如果您已经验证了。Csproj 文件是正确的,那么您有两个选项可以尝试。如果这是从源代码控件更新代码的结果,那么您可以尝试签出一个干净的副本,然后构建该副本。这对我们的一个开发人员有效,我认为在。Suo 文件或类似的东西。控件中的命令行手动强制执行包还原。问题解决方案的 nuget 文件夹:

nuget restore ..\YourSolution.sln

我用最新版本的 NuGet (2.7)和 VS2012尝试这种方法的经验是:

  • 删除. nuget 文件夹(在磁盘和解决方案中)
  • 将 NuGet.Config 文件放在所有解决方案的公共父文件夹中
  • 删除任何现有的包文件夹
  • 遍历所有 csproj 文件并更改 HintPath 以指向新位置
  • 利润

在我的示例中,我希望将所有包放在 .packages中,因此我的 NuGet.Config 看起来如下所示。

 <?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="repositorypath" value=".packages" />
</config>
</configuration>

请注意,有一些“奇怪”的事情可能会发生,但我认为它们是可以忍受的:

  • 如果你从一个解决方案“更新”一个软件包,它会立即从你的软件包文件夹中删除旧版本(它不知道你是否有另一个解决方案指向那里)。这并没有太大的困扰我,因为另一个解决方案只是在需要时恢复。
  • 如果您试图从右键单击解决方案添加软件包,如果该软件包已经存在于另一个解决方案中,它将看到它在那里,并显示“绿色勾”,而不是“安装”按钮。我通常从右键单击项目安装,所以这一点都不困扰我。

免责声明 : 我今天刚刚尝试过,我没有任何长期的经验来支持它!

现在已经没有必要修改 nuget.target 了。它已经被固定在纽杰2.8(http://nuget.codeplex.com/workitem/2921)。您只需要设置存储库路径。

以下是 NuGet 2.1的使用说明: Http://docs.nuget.org/docs/release-notes/nuget-2.1

无需编辑解决方案级别文件。

使用 VisualStudio2013和三个解决方案共享项目。

不要忘记更新解决方案级别的 NuGet (. NuGet 文件夹中的每个 NuGet.exe)。

不需要为所有项目设置公共包位置,也可以在项目中修改 HintPath,如下所示:

<HintPath>$(SolutionDir)\packages\EntityFramework.6.1.0\lib\net40\EntityFramework.dll</HintPath>

在大多数情况下,共享项目中只有很少的包,因此您可以轻松地更改它。

我认为这是更好的解决方案,当你分支代码,当设置共同回购,你必须改变相对路径,在这个解决方案中你不需要这样做。

更新我对 nuget 2.8.3的体验。相对来说很简单。所有做的都是从右键单击解决方案的 启用的包恢复。并添加了以下内容:

  <config>
<add key="repositorypath" value="..\Core\Packages" />
</config>

然后重建解决方案,它将所有包下载到我想要的文件夹,并自动更新引用。我对所有其他项目也做了同样的处理,只下载增量包,引用现有包。因此,为所有已设置的项目提供了一个通用的包存储库。

下面是启用包还原的逐步过程。

Http://blogs.4ward.it/enable-nuget-package-restore-in-visual-studio-and-tfs-2012-rc-to-building-windows-8-metro-apps/

对于那些在 VS 2013专业版NuGet版本: 2.8.60318.667的简短摘要

下面是将包定向到相对于.nuget 文件夹的路径的方法:

<configuration>
<config>
<add key="repositoryPath" value="../Dependencies" />
</config>
</configuration>

例如,如果您的解决方案(。Sln 文件)位于 C: Projects MySolution 中,当您启用 NuGet 包恢复时,。Nuget 文件夹的创建方式如下: C: Projects MySolution.nuget,包将下载到如下目录: C: Projects MySolution Dependences

注意: 由于某些(未知)原因,每次更新“ RepositoryPath”时,都必须关闭并重新打开解决方案,以使更改生效

来自 Visual Studio 2013 Update 4 and Nugget Package Manager version > 2.8.5..。

在存储库的根目录中创建 nuget.config 文件。

文件内容:

<configuration>
<config>
<add key="repositoryPath" value="packages" />
</config>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
</packageSources>
</configuration>

这将导致所有的包都转到 nuget.config 文件级别的包文件夹。

现在,您可以使用“ update-package-reinstall”命令来访问每个.sln nuget 控制台

如果在同一级别上有多个存储库,并且要在它们之间共享同一个包文件夹,请尝试使用一种方法向上放置一个文件夹。

 <add key="repositoryPath" value="..\packages" />

但是这种方式会导致 nuget 包引用 csproj 指向存储库路径之外的一个文件夹。

我有 NuGet 版本2.8.50926和 VS 2013。您不需要使用多个 nuget.config 文件,也不需要使用复杂的目录结构。只需修改这里的默认文件:

%APPDATA%\Roaming\NuGet\NuGet.Config

以下是我的档案内容:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="repositoryPath" value="C:\Projects\nugetpackages" />
</config>
<activePackageSource>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
</activePackageSource>
</configuration>

所以不管解决方案在哪里,所有的包都会进入“ C: Projects nugetpackage”文件夹。

在所有解决方案中,只需删除现有的“软件包”文件夹。然后构建您的解决方案,NuGet 将自动在您指定的新的集中目录中恢复丢失的包。

只有硬链接/包到所需的共享位置。这样,对于其他没有特殊包位置的用户,您的项目就不会中断。

以管理员身份打开命令提示符并使用

mklink /prefix link_path Target_file/folder_path

对于任何有意义的解决方案,上述答案都是不够的。非常简单,一个复杂的 TFS 工作区结构具有不同的相对路径、分支、共享项目等,这使得单个中央存储库不可能存在。

使用($SolutionDir)是朝着正确方向迈出的一步,但是使用($SolutionDir)手工编写 csproj 文件将变得非常繁琐,因为代码库中有数百个定期更新的包(每次更新发生时,HintPath 都会被一个新的相对路径覆盖)。如果必须运行 Update-Package-Reinstall,会发生什么。

有一个伟大的解决方案称为 NugetReferenceHintPathRewrite。它在构建之前自动将($SolutionDir)注入到 HintPath 中(而不需要实际更改 csproj 文件)。我想它可以很容易地被合并到自动构建系统中

我编写了一个 NuGet 包,它可以透明地将项目中的所有 NuGet 引用转换为 $(SolutionDir)相对格式。它使用构建时 XSLT 转换来实现这一点,因此您不需要手动修改项目文件。您可以自由地更新您的软件包,它不会打破任何东西。

Https://www.nuget.org/packages/nugetrelativerefs

或者,如果您使用 VisualStudio2015Update3,您只需将包引用迁移到 project.json表单,如下所述: Https://oren.codes/2016/02/08/project-json-all-the-things

对于那些使用 paket 作为包管理器的用户,您的依赖项文件有一个自动符号链接选项:

storage: symlink

顺便说一句: paket 杠杆 nuget

参考资料: https://fsprojects.github.io/Paket/dependencies-file.html

如果希望尽可能少地修改,可以使用脚本定期清理子目录。也就是说。Nuget 的默认行为是将文件从全局位置复制到本地包文件夹,因此事后删除这些文件。

我只是使用 NTFS 连接使所有的包文件夹直接指向存储库根目录之上的单个文件夹。效果很好。不存在跨多个解决方案的并行包恢复问题。这样做的一个好处是,您不必在源代码中重新配置任何东西,比如在您的。Csproj 文件。它只是让文件系统处理单个包文件夹的重定向和模拟。

只是要小心“ git”问题。虽然通过命令行显示的“ git status”没有显示非暂存的更改,但是我注意到 GitKraken 将“ package”连接视为非暂存的 文件。当你点击它的时候,它甚至会显示一些错误,比如“ file is a directory”。GitKraken 也将尝试隐藏这个“文件”,如果你重新定位,破坏连接,并恢复它作为一个实际的文件,其中包含原始文件路径的文本。非常奇怪的行为。也许可以通过确保将 文件包添加到您的。吉蒂诺尔。