如何在 Visual Studio 中启用 NuGet 包还原?

How do I enable NuGet Package Restore in Visual Studio?

堆栈上有一个 similar post,但这对我的问题没有帮助,可能是因为我使用的是 Visual Studio 2015。

如何让 "Enable NuGet Package Restore" 选项出现在 VS2015 中?

我选择了“文件”>“新建项目”并创建了一个空ASP.NET Web 应用程序。我正在寻找这个菜单选项。

我应该提一下,我已经在我的项目文件夹中查找了任何 pre-existing 个 nuGet 文件,并且有 none.

我想对于 asp.net 4 项目,我们正在转向自动恢复,因此没有必要这样做。对于较旧的项目,我认为需要进行一些转换工作。

http://docs.nuget.org/docs/workflows/migrating-to-automatic-package-restore

如果您有任何问题或缺少任何包,只需右键单击您的项目并select“管理解决方案的 NuGet 包...” .单击此按钮后,将打开一个屏幕,您会在其中看到一个菜单栏,上面写着 "Restore":

点击它,将自动安装所需的包。
我相信这就是您要找的,这解决了我的问题。

花了太长时间,但我终于在 Migrating MSBuild-Integrated solutions to Automatic Package Restore 上找到了这篇文档,并且我能够使用此处描述的方法解决问题。

  1. 从解决方案中删除 '.nuget' 解决方案目录
  2. 从您的 .csproj.vbproj 文件中删除对 nuget.targets 的所有引用。虽然没有官方支持,但如果您有很多项目需要清理,该文档链接到 PowerShell script。我手动编辑了我的,所以我不能就我的体验提供任何反馈。

手动编辑文件时,您需要查找以下内容:

解决方案文件 (.sln)

Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{F4AEBB8B-A367-424E-8B14-F611C9667A85}"
ProjectSection(SolutionItems) = preProject
    .nuget\NuGet.Config = .nuget\NuGet.Config
    .nuget\NuGet.exe = .nuget\NuGet.exe
    .nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject

项目文件 (.csproj / .vbproj)

  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
  </Target>

您可以选择从 "packages" 文件夹和 select "Manage NuGet Packages for Solution..." 中删除所有文件夹。在这种情况下,"Restore" 按钮出现在 NuGet 包 Windows 上。

Microsoft 已在 VS2015 中放弃对 'Enable NuGet Package Restore' 的支持,您需要进行一些手动更改以迁移旧解决方案或将功能添加到新解决方案。 NuGet Package Restore.

中对新功能进行了很好的描述

此处还有针对现有项目(如前所述)的迁移指南:NuGet Migration Guide

升级时:

  1. 不要删除 .nuget 目录。
  2. 删除 nuget.exe 和 nuget.targets 文件。
  3. 离开nuget.config.
  4. 手动清除每个项目文件中对 NuGet 目标的任何引用。提到的 Powershell 脚本似乎弊大于利。

新建项目时:

  1. 在您的 Visual Studio 2015 解决方案中,创建一个名为 .nuget 的解决方案目录。

  2. 创建解决方案目录(.sln 文件所在的位置)的实际目录并将其命名为 .nuget(请注意,解决方案目录与实际文件系统目录不同,即使它们同名)。

  3. 在名为 nuget.config 的 .nuget 目录中创建一个文件。

  4. 将 'nuget.config' 添加到步骤 #2 中创建的解决方案目录中。

  5. 将以下文本放入 nuget.config 文件中:

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

此配置文件将允许您将所有包合并到一个地方,这样您的文件系统上就不会出现同一个包的 20 个不同副本。相对路径将根据您的解决方案目录架构而改变,但它应该指向所有解决方案通用的目录。

您需要在执行第 5 步后重新启动 visual studio。Nuget 将无法识别更改,直到您这样做。

最后,您可能必须使用 'Nuget Package Manager for Solutions' 卸载并重新安装软件包。我不知道这是我 运行 的 Powershell 脚本的副作用,还是只是一种让 NuGet 重新启动的方法。完成所有这些步骤后,当我从 TFVC 签出项目时,我复杂的构建架构可以完美地运行新包。

将带有 nuget 包的项目从 Vx20XX 升级到 VS2015 时,您可能会遇到 nuget 包问题。

错误消息示例: 此项目引用了此计算机上缺少的 NuGet 包。启用 NuGet 包还原以下载它们。

2016-02-06 更新:我有一个 link 的信息,但它不再有效。我怀疑最近的路径已经解决了问题???

我写了一个小程序解决了我的问题 MSBuild-Integrated package restore vs. Automatic Package Restore

您可以下载该工具的可执行文件here

请告诉我结果:-) !

参考代码:

<Window x:Class="FixNuGetProblemsInVs2015.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:FixNuGetProblemsInVs2015"
        mc:Ignorable="d"
        Title="Fix NuGet Packages problems in Visual Studio 2015 (By Eric Ouellet)" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="10"></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Row="0" Grid.Column="0">Root directory of projects</TextBlock>
        <Grid Grid.Row="0" Grid.Column="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
            </Grid.ColumnDefinitions>

            <TextBox Grid.Column="0" Name="DirProjects"></TextBox>
            <Button Grid.Column="1" VerticalAlignment="Bottom" Name="BrowseDirProjects" Click="BrowseDirProjectsOnClick">Browse...</Button>
        </Grid>

        <!--<TextBlock Grid.Row="1" Grid.Column="0">Directory of NuGet Packages</TextBlock>
        <Grid Grid.Row="1" Grid.Column="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
            </Grid.ColumnDefinitions>

            <TextBox Grid.Column="0" Name="DirPackages"></TextBox>
            <Button Grid.Column="1"  Name="BrowseDirPackages" Click="BrowseDirPackagesOnClick">Browse...</Button>
        </Grid>-->

        <TextBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" Name="TxtLog" IsReadOnly="True"></TextBox>

        <Button Grid.Row="3" Grid.Column="0" Click="ButtonRevertOnClick">Revert back</Button>
        <Button Grid.Row="3" Grid.Column="2" Click="ButtonFixOnClick">Fix</Button>
    </Grid>
</Window>


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using System.Xml.Linq;
using Application = System.Windows.Application;
using MessageBox = System.Windows.MessageBox;

/// <summary>
/// Applying recommanded modifications in section : "MSBuild-Integrated package restore vs. Automatic Package Restore"
/// of : http://docs.nuget.org/Consume/Package-Restore/Migrating-to-Automatic-Package-Restore
/// </summary>

namespace FixNuGetProblemsInVs2015
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DirProjects.Text = @"c:\prj";
            // DirPackages.Text = @"C:\PRJ\NuGetPackages";
        }

        private void BrowseDirProjectsOnClick(object sender, RoutedEventArgs e)
        {
            FolderBrowserDialog dlg = new FolderBrowserDialog();
            dlg.SelectedPath = DirProjects.Text;
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                DirProjects.Text = dlg.SelectedPath;
            }
        }

        //private void BrowseDirPackagesOnClick(object sender, RoutedEventArgs e)
        //{
        //  FolderBrowserDialog dlg = new FolderBrowserDialog();
        //  dlg.SelectedPath = DirPackages.Text;
        //  if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        //  {
        //      DirPackages.Text = dlg.SelectedPath;
        //  }
        //}

        // private string _dirPackages;

        private void ButtonFixOnClick(object sender, RoutedEventArgs e)
        {
            DoJob(false);
        }

        private void ButtonRevertOnClick(object sender, RoutedEventArgs e)
        {
            DoJob(true);
        }

        private void DoJob(bool revert = false)
        {
            TxtLog.Text = "";

            string dirProjects = DirProjects.Text;
            // _dirPackages = DirPackages.Text;

            if (!Directory.Exists(dirProjects))
            {
                MessageBox.Show("Projects directory does not exists: " + dirProjects);
                return;
            }

            //if (!Directory.Exists(_dirPackages))
            //{
            //  MessageBox.Show("Packages directory does not exists: " + _dirPackages);
            //  return;
            //}

            RecurseFolder(dirProjects, revert);
        }

        private void RecurseFolder(string dirProjects, bool revert = false)
        {
            if (revert)
            {
                Revert(dirProjects);
            }
            else
            {
                FixFolder(dirProjects);
            }

            foreach (string subfolder in Directory.EnumerateDirectories(dirProjects))
            {
                RecurseFolder(subfolder, revert);
            }
        }

        private const string BackupSuffix = ".fix_nuget_backup";

        private void Revert(string dirProject)
        {
            foreach (string filename in Directory.EnumerateFiles(dirProject))
            {
                if (filename.ToLower().EndsWith(BackupSuffix))
                {
                    string original = filename.Substring(0, filename.Length - BackupSuffix.Length);
                    if (File.Exists(original))
                    {
                        File.Delete(original);                                          
                    }
                    File.Move(filename, original);
                    Log("File reverted: " + filename + " ==> " + original);
                }
            }
        }

        private void FixFolder(string dirProject)
        {
            BackupFile(System.IO.Path.Combine(dirProject, "nuget.targets"));
            BackupFile(System.IO.Path.Combine(dirProject, "nuget.exe"));

            foreach (string filename in Directory.EnumerateFiles(dirProject))
            {
                if (filename.ToLower().EndsWith(".csproj"))
                {
                    FromProjectFileRemoveNugetTargets(filename);
                }
            }
        }

        private void BackupFile(string path)
        {
            if (File.Exists(path))
            {
                string backup = path + BackupSuffix;
                if (!File.Exists(backup))
                {
                    File.Move(path, backup);
                    Log("File backup: " + backup);
                }
                else
                {
                    Log("Project has already a backup: " + backup);
                }
            }
        }

        private void FromProjectFileRemoveNugetTargets(string prjFilename)
        {
            XDocument xml = XDocument.Load(prjFilename);

            List<XElement> elementsToRemove = new List<XElement>();

            foreach (XElement element in xml.Descendants())
            {
                if (element.Name.LocalName == "Import")
                {
                    var att = element.Attribute("Project");
                    if (att != null)
                    {
                        if (att.Value.Contains("NuGet.targets"))
                        {
                            elementsToRemove.Add(element);
                        }
                    }
                }

                if (element.Name.LocalName == "Target")
                {
                    var att = element.Attribute("Name");
                    if (att != null && att.Value == "EnsureNuGetPackageBuildImports")
                    {
                        elementsToRemove.Add(element);
                    }
                }
            }

            if (elementsToRemove.Count > 0)
            {
                elementsToRemove.ForEach(element => element.Remove());
                BackupFile(prjFilename);
                xml.Save(prjFilename);
                Log("Project updated: " + prjFilename);
            }
        }

        private void Log(string msg)
        {
            TxtLog.Text += msg + "\r\n";
        }

    }
}

Ivan Branets 的解决方案本质上是为我解决了这个问题,但可以分享更多细节。

就我而言,我在 VS 2015 中使用 Auto Package restoreTFS .这些都是非常默认的东西。

问题是当另一个开发人员试图从 TFS 获得解决方案时,一些包没有完全恢复。 (为什么,我还不太确定。)但是 packages 文件夹包含一个用于引用和 NuGet 包的文件夹,但它没有得到扩展(比如缺少一个包含 .dll 的 lib 文件夹。)这一半在那里,但不是很正确的概念阻止了包的恢复。

您会认出这一点,因为参考会有一个黄色感叹号表示未解决。

因此,解决方案删除包中的文件夹消除了包恢复阻塞问题。然后您可以右键单击顶级解决方案级别以获得恢复包的选项,现在它应该可以工作了。

更简单,将 .nuget 文件夹添加到您的解决方案中,然后 'Restore Nuget Packages' 将出现(不确定是否需要存在 nuget.exe 才能正常工作)。

查看 visual studio 中的参考资料并查看缺少哪些包。 现在右键单击 Visual 中的解决方案,然后单击文件资源管理器中的打开文件夹。 现在打开包文件夹并删除丢失的包文件夹。 打开 visual studio 并构建解决方案。所有丢失的包都将被恢复。 如果对我有帮助,请标记为答案。

这种方法对我有用:

  • 关闭 VS2015
  • 在 VS2013 中临时打开解决方案并通过右键单击解决方案启用 nuget 包还原(我也进行了重建,但我怀疑不需要)。
  • 关闭 VS2013
  • 在VS2015中重新打开解决方案

您现在也在 VS2015 中启用了 nuget 包还原

我在尝试构建示例项目时遇到了同样的问题 gplus-quickstart-csharp-master

我仔细查看了错误消息并找到了克服此错误的解决方法,希望这会有所帮助。

  • 右键单击解决方案文件并在 windows 资源管理器中打开。
  • NuGet.Config、NuGet.exe、NuGet.targets 复制 .nuget 文件夹(下载 link 或者简单地从其他项目复制并替换)
  • 尝试重建解决方案。

尽情享受吧!!

我不得不删除包文件夹关闭并重新打开 (VS2015) 解决方案。我没有迁移,也没有将包签入源代码管理。我只能说有些东西搞砸了,这解决了它。

也可能是 运行 在您尝试安装程序包时该程序的结果。如果您在内置 IIS 处于后台 运行 时尝试单击它,它会显示为灰色。

如果其他人在 Visual Studio 2017 年发现此问题,请确保项目是通过 .sln 文件而不是文件夹打开的,因为如果 visual studio 将不会选择设置它是由文件夹打开的。如果您为 git 使用 Visual Studio 在线服务,默认情况下会发生这种情况。

正如 Mike 已经提到的,VS2015 中没有选项 'Enable NuGet Package Restore'。您必须手动调用恢复过程。使用 NuGet 包管理控制台 是一个不错的方法 - 不会弄乱文件和目录:单击进入 'Quick start' 字段(通常在右上角),输入 console,打开管理控制台,输入命令:

Update-Package –reinstall

这将重新安装您解决方案中所有项目的所有包。要指定单个项目,请输入:

Update-Package –reinstall -ProjectName MyProject

当然,只有当 Restore 按钮(VS2015 提供的 有时 )不可用时才需要这样做。此处列出并解释了更多有用的更新命令:https://docs.microsoft.com/en-us/nuget/consume-packages/reinstalling-and-updating-packages

Package Manager console (Visual Studio, Tools > NuGet Package Manager > Package Manager Console): Run the Update-Package -reinstall -ProjectName command where is the name of the affected project as it appears in Solution Explorer. Use Update-Package -reinstall by itself to restore all packages in the solution. See Update-Package. You can also reinstall a single package, if desired.

来自 https://docs.microsoft.com/en-us/nuget/quickstart/restore

关闭VS。删除 packages 文件夹下的所有内容。重新打开您的解决方案。右键单击您的项目,select 'Manage nuget packages...'。您会看到 'Nuget Package Manager' window 顶部出现一个黄色条,要求您恢复包。这对我有用。

我用了msbuild /t:restore.


信用和来源:

我的问题是 MSBuild 所以我关注了@Vinney Kelly的link:Migrating MSBuild-Integrated solutions to Automatic Package Restore

和...

这很有魅力 =]

MSBuild: use the msbuild /t:restore command, which restores packages packages listed in the project file (PackageReference only). Available only in NuGet 4.x+ and MSBuild 15.1+, which are included with Visual Studio 2017. nuget restore and dotnet restore both use this command for applicable projects.

帮助我完成 工具 >>> Nuget 包管理器 >>> 常规 然后勾选选项 允许 Nuget 下载丢失的包在 visual studio.

构建期间自动检查丢失的包

对于 .NET Core 项目、运行 dotnet restoredotnet build NuGet Package Manager Console 中的命令(自动 运行恢复)

您可以 运行 从

控制台

Tools > NuGet Package Manager > Package Manager Console

使用此命令恢复所有包

dotnet restore

如果所有其他方法都失败了(或者可能在此之前),您可能需要检查并查看 NuGet 是否是包源。我安装了 VS2017,默认情况下不存在。我觉得有点奇怪。

  1. 工具 - NuGet 包管理器 - 包管理器设置
  2. 单击对话框左侧导航栏上的 'Package Sources'。
  3. 使用加号 (+) 添加 Nuget URL: https://api.nuget.org/v3/index.json

我遇到了同样的问题。我正在尝试将在 Visual Studio 2015 年创建的 MVC 项目添加到我在 Visual Studio 2019 年创建的解决方案中。

Visual Studio 2019 上已经存在项目,因此添加我在 VS 2015 上创建的这个现有项目会触发同样的错误。我已经尝试了这里的所有答案,但它并没有解决问题。

我所做的只是将 .nuget 文件夹放在解决方案文件夹中。原来文件夹的层级是这样的:

Solution Folder (VS 2019)
  -> MVC 1 Project
  -> MVC 2 Project
  -> MVC 3 Project (Project that I am adding)
         -> .nuget folder (It contains a .nuget folder)

因此,当我将 .nuget 文件夹移动到解决方案文件夹本身时,问题得到解决:

    Solution Folder (VS 2019)
  -> MVC 1 Project
  -> MVC 2 Project
  -> MVC 3 Project (Project that I am adding)
  -> .nuget folder (It contains a .nuget folder)

VS 2019 版本 16.4.4 针对 .NET Core 3.1 的解决方案

几乎尝试了这里提出的所有解决方案后,我关闭了VS。 当我重新打开它时,几秒钟后一切恢复正常...