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

我一直在使用NuGet来从外部和内部包源中检索包,这非常方便。 但是我已经意识到,软件包默认存储在每个解决scheme中,当一些NuGet参考项目包含在几个解决scheme中时,这是非常令人沮丧的。 然后,引用被更改为其他解决scheme包文件夹,实际上可能对其他开发人员或构build机器不可用。

我已经看到,在NuGet的2.1版本中,有许多方法可以指出一个通用的软件包位置(可能在项目的根目录下,我们使用的是TFS源代码控制),请参阅发行说明 。 我正在使用NuGet v2.7

但我已经尝试添加nuget.config文件,而没有看到任何影响。 包仍然存储在解决scheme文件夹中。 有什么我错过了吗? 似乎有不同的XML节点的结构添加到nuget.config文件,这取决于谁回答这个问题:Schwarziebuild议在另一个Stackoverflow线程 :

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

NuGet 2.1的发行说明(参见上面的链接)build议这种格式:

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

我不知道这其中哪一个,哪一个或哪一个最终会工作。 我已经在解决scheme层面尝试过。 nuget.config文件可以放在TFS项目的根目录下,还是必须在解决scheme目录下? 看起来,NuGet按照一定的顺序读取和应用这些文件中的设置,为什么将它们添加到多个级别是有意义的,其中解决scheme级别上的nuget.config文件将覆盖TFS项目根级别上的一个。 这能澄清吗?

我需要删除所有已安装的软件包之前,这些引用将工作? 如果有人能够提供从解决scheme特定的nuget使用情况到共同的包文件夹的分步说明,那么这个项目属于几个解决scheme,可以find他们需要的nuget包。

我有一个类似的情况与外部和内部的软件包来源与多个解决scheme中引用的项目。 我刚刚得到了我们今天的一个代码库的工作,似乎与开发人员工作站和我们的生成服务器工作。 下面的过程有这种情况(虽然它不应该很难适应有其他的公用包文件夹)。

  • 代码库
    • 项目A
    • 项目B
    • C项目
    • 解决scheme
      • 解决scheme1
      • 解决scheme2
      • 解决scheme3
      • 软件包(这是所有解决scheme共享的软件包)

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

现在这个过程比我最初解决这个问题要容易一些,并且认为是时候更新了。 一般来说,这个过程是一样的,只需要更less的步骤。 结果是解决或提供以下的过程:

  • 所有需要提交到源代码控制的内容都可以在解决scheme中查看和跟踪
  • 使用Visual Studio中的包pipe理器安装新包或更新包将使用正确的存储库path
  • 在初始configuration之后,不要对.csproj文件进行黑客攻击
  • 开发者工作站没有任何修改(代码已经准备就绪)

有一些潜在的缺点需要注意(我还没有经历过,YMMV)。 请参阅下面的Benol的回答和评论。

添加NuGet.Config

您将需要在\ Solutions \文件夹的根目录中创build一个NuGet.Config文件。 确保这是一个你创build的UTF-8编码文件,如果你不确定如何做到这一点,使用Visual Studio的文件 – >新build – >文件菜单,然后selectXML文件模板。 添加到NuGet.Config下面:

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

对于repositoryPath设置,可以使用$ token指定绝对path或相对path(推荐)。 $ token是基于NuGet.Config所在的位置($ token实际上是相对于NuGet.Config位置下的一个级别 )。 所以,如果我有\ Solutions \ NuGet.Config,我想\ Solutions \ Packages我需要指定$ \ .. \ Packages作为值。

接下来,您将需要为您解决scheme添加一个解决scheme文件夹,称为“NuGet”(右键单击您的解决scheme,添加 – >新解决scheme文件夹)。 解决scheme文件夹是只存在于Visual Studio解决scheme中的虚拟文件夹,不会在驱动器上创build实际的文件夹(并且您可以从任何位置引用文件)。 右键单击您的“NuGet”解决scheme文件夹,然后单击Add-> Existing Item并select\ Solutions \ NuGet.Config。

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

通过将NuGet.Config文件放在\ Solutions \上面的任何.sln文件中,我们正在利用NuGet从“当前工作目录”向上recursion地浏览文件夹结构,以查找要使用的NuGet.Config文件。 “当前工作目录”在这里意味着一些不同的事情,一个是NuGet.exe的执行path,另一个是.sln文件的位置。

切换你的包文件夹

首先,我强烈build议您浏览每个解决scheme文件夹并删除存在的任何\ Packages \文件夹(您需要先closuresVisual Studio)。 这使得更容易看到NuGet将新configuration的\ Packages \文件夹放在哪里,并确保指向错误的\ Packages \文件夹的任何链接都将失败,然后可以修复。

在Visual Studio中打开您的解决scheme并启动“重build全部”。 忽略所有您将收到的构build错误,这是预计在这一点上。 这应该在构build过程开始时启动NuGet包恢复function。 确认您的\ Solutions \ Packages \文件夹已经在您想要的位置创build。 如果没有,请检查您的configuration。

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

  1. 右键单击该项目,然后select卸载项目
  2. 右键单击该项目,然后select编辑your-xxx.csproj
  3. find\ packages \的任何引用并将其更新到新的位置。
    • 其中大部分将是<HintPath>引用,但不是全部。 例如,WebGrease和Microsoft.Bcl.Build将有单独的path设置,需要更新。
  4. 保存.csproj,然后右键单击该项目并selectReload Project

一旦所有的.csproj文件已经更新,启动另一个重build所有,你应该没有更多的关于缺less引用的构build错误。 此时你已经完成了,现在已经configuration了NuGet来使用一个共享的Packages文件夹。

截至2013年的VStudio NuGet 2.7.1(2.7.40906.75)

首先要记住的是,nuget.config不能控制nuget包系统中的所有path设置。 弄清楚这个特别令人困惑。 具体来说,问题是msbuild和Visual Studio(调用msbuild)不使用nuget.config中的path,而是在nuget.targets文件中重写它。

环境准备

首先,我会通过解决scheme的文件夹,并删除所有\ packages \文件夹存在。 这将有助于确保所有软件包都可见地安装到正确的文件夹中,并帮助发现整个解决scheme中的任何不良path引用。 接下来,我会确保你安装了最新的nuget Visual Studio扩展。 我也会确保你有最新的nuget.exe安装到每个解决scheme。 打开命令提示符并进入每个$(SolutionDir)\ .nuget \文件夹并执行以下命令:

 nuget update -self 

为NuGet设置通用的包文件夹path

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

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

注意:您可以使用绝对path或相对path。 请记住,如果你使用相对path$,它相对于NuGet.Config的位置下面一个级别 (相信这是一个错误)。

为MSBuild和Visual Studio设置通用的包文件夹path

打开每个$(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将把我们的相对pathparsing成绝对path。

将所有nuget软件包恢复到通用文件夹

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

 nuget restore ..\YourSolution.sln 

此时,您应该在公用位置有一个\ packages \文件夹,并且在您的任何解决scheme文件夹中都没有。 如果没有,那么validation你的path。

修复项目参考

在文本编辑器中打开每个.csproj文件,find\ packages的任何引用,并将它们更新到正确的path。 其中大部分将是<HintPath>引用,但不是全部。 例如,WebGrease和Microsoft.Bcl.Build将有单独的path设置,需要更新。

build立你的解决scheme

在Visual Studio中打开您的解决scheme并启动构build。 如果它抱怨缺less需要恢复的软件包,请不要认为软件包丢失,需要恢复(错误可能会引起误解)。 这可能是你的一个.csproj文件中的一个不好的path。 在恢复软件包之前先检查一下。

有关于缺less包的构build错误?

如果您已经validation了.csproj文件中的path是正确的,那么您有两个选项可以尝试。 如果这是从源代码控制更新代码的结果,那么您可以尝试签出一个干净的副本,然后build立。 这对我们的开发人员来说很有效,我觉得在.suo文件或类似的东西里有一个神器。 另一个选项是使用相关解决scheme的.nuget文件夹中的命令行手动强制进行程序包还原:

 nuget restore ..\YourSolution.sln 

而不是为所有项目设置通用包位置,也可以在项目中更改HintPath,如下所示:

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

在大多数情况下,在共享项目中只有很less的包,所以你可以很容易地改变它。

我认为这是更好的解决scheme,当你分支代码,设置常见的回购时,你必须改变相对path,在这个解决scheme中,你不需要这样做。

我的经验与最新版本的NuGet(2.7)和VS2012:

  • 删除.nuget文件夹(在磁盘上和解决scheme中)
  • 将NuGet.Config文件放在所有解决scheme的通用父文件夹中
  • 删除任何现有的包文件夹
  • 浏览所有的csproj文件并将HintPaths更改为指向新的位置
  • 利润

在我的情况下,我想把所有包放在.packages ,所以我的NuGet.Config如下所示。

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

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

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

免责声明 :我今天刚试过,没有长期的经验备份!

我有与2013年的NuGet版本2.8.50926.你不需要使用多个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> 

因此,无论解决scheme在哪里,所有软件包都将转到“C:\ Projects \ nugetpackages”文件夹中。

在所有的解决scheme中,只需删除现有的“包”文件夹。 然后build立你的解决scheme,NuGet会自动在你指定的新的集中目录中恢复丢失的包。

已经不需要修改nuget.targets。 它已被修复在nuget 2.8( http://nuget.codeplex.com/workitem/2921 )。 你只需要设置repositorypath。

用nuget 2.8.3更新我的经验。 这是相对简单的。 所有这些都是从右键单击解决scheme启用软件包恢复 编辑了NuGet.Config并添加了这些行:

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

然后重build解决scheme,它将所有包下载到我想要的文件夹并自动更新引用。 我对所有其他项目都做了同样的事情,只有下载增量包和引用现有包。 因此,已经设置了所有项目的通用软件包存储库。

以下是一步一步的程序来启用软件包还原。

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

从Visual Studio 2013 Update 4和块金包pipe理器版本> 2.8.5 …

在存储库的根目录下创buildnuget.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在你的存储path之外指向一个文件夹。

对于任何重要的解决scheme,上面的答案都会失败。 简而言之,具有不同相对path,分支,共享项目等的复杂的TFS工作空间结构使得单个中央存储库成为不可能。

使用($ SolutionDir)是一个正确的方向,但是使用($ SolutionDir)手动编码csproj文件在代码库中变得非常繁琐,并且会定期更新数百个软件包(每次更新时,HintPath都会被覆盖一个新的相对path)。 如果必须运行Update-Package -Reinstall,会发生什么情况。

有一个很好的解决scheme,叫做NugetReferenceHintPathRewrite 。 它在构build之前自动将($ SolutionDir)注入到HintPath中(实际上并没有改变csproj文件)。 我想它可以很容易地被合并到自动构build系统中

我编制了一个NuGet包,它将项目中的所有NuGet引用透明地转换为$(SolutionDir)相对格式。 它使用构build时XSLT转换,所以你不需要手工破解你的项目文件。 你可以自由地更新你的软件包,它不会打破。

https://www.nuget.org/packages/NugetRelativeRefs

或者,如果您使用Visual Studio 2015 Update 3,则可以将您的软件包引用移至project.json表单,如下所述: https : //oren.codes/2016/02/08/project-json-all-the-things

NuGet版本: 2.8.60318.667的 VS 2013专业版的简短摘要

这就是如何将包引导到相对于.nuget文件夹的path:

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

例如,如果您的解决scheme(.sln文件)驻留在C:\ Projects \ MySolution中,则当您启用NuGet程序包还原时,将创build.nuget文件夹,如下所示:C:\ Projects \ MySolution.nuget,将下载软件包到如下目录:C:\ Projects \ MySolution \ Dependencies

注意:对于某些(未知的)原因,每次我更新“repositoryPath”时,我必须closures并重新打开解决scheme才能使更改生效

只需硬链接/打包到所需的共享位置。 那么你的项目不会被其他用户打破,那就是没有特殊的软件包位置。

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

 mklink /prefix link_path Target_file/folder_path 

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

无需编辑解决scheme级别的文件。

适用于Visual Studio 2013和三个解决scheme共享项目。

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