【问题标题】:View NuGet package dependency hierarchy查看 NuGet 包依赖层次结构
【发布时间】:2011-07-11 17:01:20
【问题描述】:

有没有一种方法(文本或图形)来查看 NuGet 包之间的依赖关系层次结构?

【问题讨论】:

标签: c# nuget


【解决方案1】:

如果您使用新的.csproj,您可以在此处获取所有依赖项(在项目构建后):

{ProjectDir}\obj\project.assets.json

【讨论】:

  • 最简单的解决方案,干杯。
  • 不能再同意了
  • 我认为这适用于任何使用 <PackageReference> 格式而不是 packages.config 文件的 csproj。我有一个带有老式 csproj 的旧版应用程序,已修改为使用 PackageReference,并且此文件存在于我的 obj 文件夹中。
【解决方案2】:

还可以针对NuGet.Core 中的API 编写代码。通过 NuGet 安装:

install-package nuget.core

然后您可以获取存储库对象并遍历图表。这是我刚刚构建的示例应用程序:

using System;
using System.Collections.Generic;
using System.Linq;
using NuGet;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main()
        {    
            var repo = new LocalPackageRepository(@"C:\Code\Common\Group\Business-Logic\packages");
            IQueryable<IPackage> packages = repo.GetPackages();
            OutputGraph(repo, packages, 0);
        }

        static void OutputGraph(LocalPackageRepository repository, IEnumerable<IPackage> packages, int depth)
        {
            foreach (IPackage package in packages)
            {
                Console.WriteLine("{0}{1} v{2}", new string(' ', depth), package.Id, package.Version);

                IList<IPackage> dependentPackages = new List<IPackage>();
                foreach (var dependency in package.Dependencies)
                {
                    dependentPackages.Add(repository.FindPackage(dependency.Id, dependency.VersionSpec.ToString()));
                }

                OutputGraph(repository, dependentPackages, depth += 3);
            }
        }
    }
}

在我的例子中,这个应用程序输出如下内容:

MyCompany.Castle v1.1.0.3
   Castle.Windsor v2.5.3
      Castle.Core v2.5.2
      MyCompany.Common v1.1.0.6
         CommonServiceLocator v1.0
            MyCompany.Enum v1.1.0.7
   MyCompany.Common v1.1.0.6
      CommonServiceLocator v1.0
         MyCompany.Enum v1.1.0.7
      MyCompany.Enum v1.1.0.7
         MyCompany.Versioning v1.3
            Castle.Core v2.5.2
               Castle.Windsor v2.5.3
                  Castle.Core v2.5.2
                  CommonServiceLocator v1.0
                     NUnit v2.5.10.11092
                        RhinoMocks v3.6

【讨论】:

  • NuGet 中有一个 ResolveDependency 扩展方法可以使用。
  • depth += 3 可能是一个错误,更改为 depth + 3。然后您可以在左侧看到所有包,并且只有这些包的依赖项是缩进的
  • 我尝试将此更新到最新版本的 NuGet,但我的编辑被拒绝。将 foreach 依赖更改为 package.DependencySets 并添加另一个 foreach 循环获取依赖。
  • @davidfowl 在 NuGet.Client 中有类似的功能吗?
  • 确保在 .Net Framework 控制台应用程序而不是 .Net Core 应用程序中运行它。核心版本将无法访问所有框架依赖项,并且会在调用FindPackages时崩溃
【解决方案3】:

由于这是一个老问题,请务必注意以下几点:

这是新 csproj 格式的内置功能。在 Visual Studio 2017 及更高版本中,打开解决方案资源管理器,您可以找到如下包:

{Your project}->Dependencies->Packages

您可以打开每个 NuGet 依赖关系树并使用它递归运行,不仅可以有效查看特定包的依赖关系树,还可以查看您的项目实际安装了哪些 NuGet 包。

【讨论】:

  • 您在哪里看到“依赖项”?我在解决方案资源管理器中的任何地方都没有看到它。
  • 如果您正在处理 .Net Standard 或 .Net Core 项目,则可以通过打开每个项目的树来查看它。但是,如果您正在处理 .Net Framework 项目,那么您应该使用其他响应之一。
  • 有人知道这是否会成为我们这些使用 .Net Frameweork 的人的解决方案资源管理器吗?
  • 这甚至适用于解决方案资源管理器搜索(至少在 VS 2019 中),对于快速跟踪导致某个包的依赖链非常有用。
【解决方案4】:

我添加了一个与最新版本的 nuget-core 兼容的解决方案

install-package nuget.core

这是获取依赖关系图的控制台应用

    class Program
    {
        static void Main()
        {
            Console.Write("Enter the local repo folder: ");
            var repoFolder = Console.ReadLine();

            var repo = new LocalPackageRepository(repoFolder);
            IQueryable<IPackage> packages = repo.GetPackages();
            OutputGraph(repo, packages, 0);
        }

        static void OutputGraph(LocalPackageRepository repository, IEnumerable<IPackage> packages, int depth)
        {
            foreach (IPackage package in packages)
            {
                Console.WriteLine("{0}{1} v{2}", new string(' ', depth), package.Id, package.Version);

                IList<IPackage> dependentPackages = new List<IPackage>();
                foreach (var dependencySet in package.DependencySets)
                {
                    foreach (var dependency in dependencySet.Dependencies)
                    {
                        var dependentPackage = repository.FindPackage(dependency.Id, dependency.VersionSpec, true, true);
                        if (dependentPackage != null)
                        {
                            dependentPackages.Add(dependentPackage);
                        }
                    }       
                }

                OutputGraph(repository, dependentPackages, depth += 3);
            }
        }
    }

【讨论】:

    【解决方案5】:

    类似于@neil-barnwell 解决方案,但适用于 NuGet.Core 2.7+

    Install-Package NuGet.Core
    

    这里是代码

    using System;
    using System.Linq;
    using System.Runtime.Versioning;
    using System.IO;
    using NuGet;
    
    public class Program
    {
        public static void Main(string[] args)
        {
            var frameworkName = new FrameworkName(".NETFramework, Version=4.0");
    
            // var packageSource = "https://www.nuget.org/api/v2/";
            var packageSource = Path.Combine(Environment.GetEnvironmentVariable("LocalAppData"), "NuGet", "Cache");
    
            var repository = PackageRepositoryFactory.Default.CreateRepository(packageSource);
            const bool prerelease = false;
    
            var packages = repository.GetPackages()
                .Where(p => prerelease ? p.IsAbsoluteLatestVersion : p.IsLatestVersion)
                .Where(p => VersionUtility.IsCompatible(frameworkName, p.GetSupportedFrameworks()));
    
            foreach (IPackage package in packages)
            {
                GetValue(repository, frameworkName, package, prerelease, 0);
            }
    
            Console.WriteLine();
            Console.WriteLine("Press Enter...");
            Console.ReadLine();
        }
    
        private static void GetValue(IPackageRepository repository, FrameworkName frameworkName, IPackage package, bool prerelease, int level)
        {
    
            Console.WriteLine("{0}{1}", new string(' ', level * 3), package);
            foreach (PackageDependency dependency in package.GetCompatiblePackageDependencies(frameworkName))
            {
                IPackage subPackage = repository.ResolveDependency(dependency, prerelease, true);
                GetValue(repository, frameworkName, subPackage, prerelease, level + 1);
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      您的另一个选择是使用nuget-deps-tree npm 包。 它支持 packages.config 格式和 .NET 项目使用的较新的 assets 格式。

      【讨论】:

      • 不幸的是,nuget-deps-tree 的输出对于随意查看依赖树几乎毫无用处,但它是我见过的唯一真正有效的解决方案。
      【解决方案7】:

      我找到了一个不错的NPM package 将依赖关系树打印到控制台。当然,如果你不介意使用/安装 NPM/Node.JS。

      考虑其他解决方案,这是最简单的一种,您不需要编写自己的代码或注册某些东西,并且您会得到您所期望的依赖树。但它只适用于packages.config 格式。

      我不敢相信免费的 Visual Studio 版本或 nuget.exe 也没有此功能。

      【讨论】:

      • 这很好用(对于 packages.config 格式)并且应该有更多的投票!请注意,为依赖项显示的版本号不是最低要求的版本(或范围),而是实际安装的版本。 (很高兴知道哪些软件包依赖于非常旧版本的依赖项,因为当前安装的版本中可能存在重大更改。)
      • 提供的其他答案不适用于我的 Xamarin Visual Studio 解决方案,但这个答案可以,因为它只查看 packages.config。谢谢
      【解决方案8】:

      I Can Has .NET Core (GitHub repository) 生成漂亮的 NuGet 依赖关系图以及 Graphviz 表示。顾名思义,您还可以免费获得 .NET Core 兼容性信息。

      如果您更喜欢在计算机上本地运行它,I Can Has .NET Core 还提供console 模式。

      【讨论】:

      【解决方案9】:

      https://github.com/mikehadlow/AsmSpy 使用它来识别项目中的程序集版本

      【讨论】:

        【解决方案10】:

        仅供参考,MyGet.org 内置了这种可视化。您可以在 Feed 详细信息页面上查看依赖关系图。

        【讨论】:

          【解决方案11】:

          从 NuGet 1.4 可视化的包应该可以工作。见http://docs.nuget.org/docs/release-notes/nuget-1.4

          【讨论】:

          • 啊,这很有帮助,但不幸的是,我只有 VS Pro,并且用于此的工具仅在 Ultimate 中。 :(
          • 不幸的是,它没有包含在专业版中。恕我直言,考虑到 NuGet 即使在快速版本中也可用,它的所有功能即使在快速版本中也应该可用。包图信息有时非常有用。
          猜你喜欢
          • 2015-12-03
          • 1970-01-01
          • 1970-01-01
          • 2019-02-03
          • 2012-08-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-01
          相关资源
          最近更新 更多