127

Is there a way, either textual or graphical, to view the hierarchy of dependencies between NuGet packages?

Pang
  • 9,564
  • 146
  • 81
  • 122
Neil Barnwell
  • 41,080
  • 29
  • 148
  • 220

11 Answers11

86

If you're using the new .csproj, you could get all dependencies with reference in here (after project built):

{ProjectDir}\obj\project.assets.json

enter image description here

John Jang
  • 2,567
  • 24
  • 28
  • 1
    simplest and to the point solution, cheers. – Pellet Dec 19 '20 at 07:28
  • 7
    I think this works in any csproj that uses the `` format instead of a packages.config file. I have a legacy app with an oldschool csproj, modified to use PackageReference and this file exists in my obj folder. – Steven Liekens Sep 21 '21 at 12:05
34

Like @neil-barnwell solution, but works with NuGet.Core 2.7+

Install-Package NuGet.Core

Here is the code

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);
        }
    }
}
Gian Marco
  • 22,140
  • 8
  • 55
  • 44
28

It is also possible to write code against the API in NuGet.Core. Install it via NuGet:

install-package nuget.core

Then you can get a repository object and walk the graph. Here's a sample app I just built:

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);
            }
        }
    }
}

In my case, this app outputs something like this:

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
Pang
  • 9,564
  • 146
  • 81
  • 122
Neil Barnwell
  • 41,080
  • 29
  • 148
  • 220
  • 2
    There's a ResolveDependency extension method in NuGet that you can use. – davidfowl Jul 19 '11 at 09:17
  • 7
    depth += 3 is probably a bug, change to depth + 3. You can then see all packages on the left and only dependencies of that packages are indented – WhiteKnight Sep 26 '13 at 16:59
  • 5
    I tried to update this to the latest version of NuGet, but my edit was rejected. Change foreach dependency to package.DependencySets and add another foreach loop get the dependency. – WhiteKnight Sep 26 '13 at 17:08
  • @davidfowl is there any feature like that in NuGet.Client? – Konrad Nov 08 '18 at 14:21
  • 1
    Make sure you run this in a .Net Framework console app and not a .Net Core app. The core version will not have access to all the framework dependencies and will blow up on the call to `FindPackages` – Adrian Feb 02 '21 at 21:51
  • 1
    Also the Nuget.Core package should be 1.5.x or lower. With higher versions the code won't compile. – robbie fan May 17 '22 at 07:43
  • 1
    As of 2022, the package is deprecated since it works on v2 api only – Yennefer Oct 03 '22 at 09:55
21

I've found a nice NPM package to print the dependency tree into console. Of course if you don't mind using/installing NPM/Node.JS.

Considering other solutions, this is the most simple one, you don't need to write your own code or register something, and you get just such dependency tree as you expect. But it works only with packages.config format.

I can't believe this functionality is absent in free Visual Studio editions or nuget.exe too.

N. Kudryavtsev
  • 3,556
  • 1
  • 26
  • 30
  • 5
    This works great (for packages.config format) and should have more votes! Note that the version numbers shown for dependencies are not the minimum required version (or range) but the actual version installed. (It would be nice to know which packages depend on very old versions of dependencies, because there might be breaking changes in the currently installed version.) – YipYip Mar 24 '18 at 00:12
  • The other answers provided did not work for my Xamarin Visual Studio solution but this one does because it only looks at packages.config. Thank you – stepheaw Jul 25 '18 at 16:02
  • Can confirm it after several hours of trial an error - THIS ANSWER WORKS. Thanks – Kraego Jan 11 '23 at 20:44
13

I Can Has .NET Core (GitHub repository) produces nice graphs of NuGet dependencies along with a Graphviz representation. And as its name implies, you also get .NET Core compatibility information for free.

If you prefer to run it locally on your computer, I Can Has .NET Core also offers a console mode.

NuGet dependencies graph sample (web)

NuGet dependencies graph sample (Graphviz)

0xced
  • 25,219
  • 10
  • 103
  • 255
  • 7
    *"We have decided to close down https://icanhasdot.net/ in May 2020."* — [GitHub - OctopusDeploy/ICanHasDotnetCore](https://github.com/OctopusDeploy/ICanHasDotnetCore) – Pang Mar 15 '21 at 01:36
  • Site is now closed down, having served its purpose. – jaygeek Sep 13 '21 at 17:47
9

I add a compatible solution with the latest version of nuget-core

install-package nuget.core

This is the console App to get the dependencies graph

    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);
            }
        }
    }
c0m4
  • 4,343
  • 10
  • 35
  • 40
Javier Solis
  • 91
  • 1
  • 2
7

Since this is an old question, it is important to note the following:

This is a built-in feature in the new csproj format. In Visual Studio 2017 and up, open the Solution Explorer and you can find you packages like:

{Your project}->Dependencies->Packages

You can open each NuGet dependency tree and run with it recursively, effectively seeing not only the dependency tree for specific packages, but also which NuGet packages your project actually installs.

Josef Ginerman
  • 1,460
  • 13
  • 24
  • 4
    Where exactly do you see "Dependencies"? I don't see it anywhere in the Solution Explorer. – Ed S. Dec 18 '18 at 15:51
  • 3
    If you're working on a .Net Standard or .Net Core project then you can see it by opening each project's tree. But if you're working on a .Net Framework project then you should use one of the other responses. – Josef Ginerman Dec 18 '18 at 18:59
  • 3
    Anyone that knows if this is going to make it into the Solution Explorer for those of us who use .Net Frameweork? – Mats Isaksson Nov 19 '19 at 13:04
  • 1
    This even works with Solution Explorer search (at least in VS 2019), super useful to quickly trace the dependency chain leading to a certain package. – Ohad Schneider Mar 25 '21 at 17:29
  • There is a downside to this answer: In Solution Explorer the version number that is shown behind each dependency is not the version number needed by this special dependency, but the highest version that is required over all dependencies. If you need to find out exactly which Nuget packages pushes a required version number up, you will have to resort to the answer of @JohnJang (look into \obj\project.assets.json). – Jpsy Jan 11 '23 at 16:19
7

Package Visualized from NuGet 1.4 should work. See http://docs.nuget.org/docs/release-notes/nuget-1.4

Eugene Petrenko
  • 4,874
  • 27
  • 36
  • 6
    Ahh that is helpful, but unfortunately I only have VS Pro, and the tools used for that are only in Ultimate. :( – Neil Barnwell Jul 11 '11 at 17:14
  • Its unfortunate that is not included in pro version. IMHO considering NuGet is available even in express versions, all its features should be available even in express versions. Package graph information is very helpful sometime. – Mazhar Qayyum May 13 '14 at 12:27
5

Another option you have is to use the nuget-deps-tree npm package. It supports both the packages.config format and the newer assets format used by .NET projects.

Eyal Ben Moshe
  • 2,400
  • 12
  • 15
  • Unfortunately, the output of nuget-deps-tree is almost useless for casual viewing of a dependency tree, but it is the only solution I've seen that actually works. – EKW Mar 16 '21 at 20:48
2

https://github.com/mikehadlow/AsmSpy using this to identify assembly version across a project

Martea
  • 507
  • 1
  • 5
  • 18
2

FYI, MyGet.org has this kind of visualization built-in. You can view dependency graphs on the Feed Details page.

Xavier Decoster
  • 14,580
  • 5
  • 35
  • 46