NuGet dependency tree [duplicate] - c#
Is there a way, either textual or graphical, to view the hierarchy of dependencies between NuGet packages?
If you're using the new .csproj, you could get all dependencies with reference in here (after project built):
{ProjectDir}\obj\project.assets.json
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);
}
}
}
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
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.
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.
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);
}
}
}
Package Visualized from NuGet 1.4 should work. See http://docs.nuget.org/docs/release-notes/nuget-1.4
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.
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.
FYI, MyGet.org has this kind of visualization built-in. You can view dependency graphs on the Feed Details page.
https://github.com/mikehadlow/AsmSpy using this to identify assembly version across a project
Related
Migrate WindowsAzure.ServiceBus to Azure.Messaging.ServiceBus
Microsoft will deprecated support of Classic API for Service Bus at November 2021 (as described here) In our code we use WindowsAzure.ServiceBus package. It is an ol package and Microsoft suggets to use new Azure.Messaging.ServiceBus package. WindowsAzure.ServiceBus package contain GetQueues(String) method. This method can use filter parameter for filtration queues by name or properties. It is very useful if a ServiceBus has many Queues. But I can't find equivalent of this feature in new Azure.Messaging.ServiceBus package. How can I implement filter feature in new package? Thanks for any help.
How can I implement filter feature in new package? You will need to use GetQueuesAsync method in ServiceBusAdministrationClient class to get this information. Please see the sample code: using System; using System.Threading.Tasks; using Azure.Messaging.ServiceBus.Administration; namespace SO67703647 { class Program { static string connectionString = "your-connection-string"; static async Task Main(string[] args) { var adminClient = new ServiceBusAdministrationClient(connectionString); var queuesListingResult = adminClient.GetQueuesAsync(); await foreach (var item in queuesListingResult) { Console.WriteLine(item.Name); } Console.WriteLine("======================="); Console.WriteLine("Press any key to terminate the application."); Console.ReadKey(); } } }
How do I get access to CimCmdlets in .NET Core when using System.Management.Automation?
Goal I would like to have access to the cmdlets in the CimCmdlets module in .NET Core within C# code. Specifically, I want to be able to use the New-CimSessionOption and New-CimSession cmdlets. NuGet Packages Microsoft.NETCore.App v2.2.0 Microsoft.Powershell.SDK v6.2.2 Simple Demo using System; using System.Management.Automation; namespace ConsoleApp1 { class Program { static void Main(string[] args) { string str; using (var ps = PowerShell.Create()) { str = ""; var results = ps.AddScript("Get-Command").Invoke(); foreach (var result in results) { str += result.ToString() + ", "; } } Console.WriteLine(str); } } } Output A:, B:, C:, cd.., cd\, Clear-Host, D:, E:, F:, G:, H:, help, I:, J:, K:, L:, M:, mkdir, N:, O:, oss, P:, Pause, prompt, Q:, R:, S:, T:, TabExpansion2, U:, V:, W:, X:, Y:, Z:, Add-Content, Add-History, Add-Member, Add-Type, Clear-Content, Clear-History, Clear-Item, Clear-ItemProperty, Clear-Variable, Compare-Object, Connect-PSSession, Connect-WSMan, Convert-Path, ConvertFrom-Csv, ConvertFrom-Json, ConvertFrom-Markdown, ConvertFrom-SddlString, ConvertFrom-SecureString, ConvertFrom-StringData, ConvertTo-Csv, ConvertTo-Html, ConvertTo-Json, ConvertTo-SecureString, ConvertTo-Xml, Copy-Item, Copy-ItemProperty, Debug-Job, Debug-Process, Debug-Runspace, Disable-ExperimentalFeature, Disable-PSBreakpoint, Disable-PSRemoting, Disable-PSSessionConfiguration, Disable-RunspaceDebug, Disable-WSManCredSSP, Disconnect-PSSession, Disconnect-WSMan, Enable-ExperimentalFeature, Enable-PSBreakpoint, Enable-PSRemoting, Enable-PSSessionConfiguration, Enable-RunspaceDebug, Enable-WSManCredSSP, Enter-PSHostProcess, Enter-PSSession, Exit-PSHostProcess, Exit-PSSession, Export-Alias, Export-Clixml, Export-Csv, Export-FormatData, Export-ModuleMember, Export-PSSession, ForEach-Object, Format-Custom, Format-Hex, Format-List, Format-Table, Format-Wide, Get-Acl, Get-Alias, Get-AuthenticodeSignature, Get-ChildItem, Get-CmsMessage, Get-Command, Get-ComputerInfo, Get-Content, Get-Credential, Get-Culture, Get-Date, Get-Event, Get-EventSubscriber, Get-ExecutionPolicy, Get-ExperimentalFeature, Get-FileHash, Get-FormatData, Get-Help, Get-History, Get-Host, Get-Item, Get-ItemProperty, Get-ItemPropertyValue, Get-Job, Get-Location, Get-MarkdownOption, Get-Member, Get-Module, Get-PfxCertificate, Get-Process, Get-PSBreakpoint, Get-PSCallStack, Get-PSDrive, Get-PSHostProcessInfo, Get-PSProvider, Get-PSSession, Get-PSSessionCapability, Get-PSSessionConfiguration, Get-Random, Get-Runspace, Get-RunspaceDebug, Get-Service, Get-TimeZone, Get-TraceSource, Get-TypeData, Get-UICulture, Get-Unique, Get-Uptime, Get-Variable, Get-Verb, Get-WinEvent, Get-WSManCredSSP, Get-WSManInstance, Group-Object, Import-Alias, Import-Clixml, Import-Csv, Import-LocalizedData, Import-Module, Import-PowerShellDataFile, Import-PSSession, Invoke-Command, Invoke-Expression, Invoke-History, Invoke-Item, Invoke-RestMethod, Invoke-WebRequest, Invoke-WSManAction, Join-Path, Join-String, Measure-Command, Measure-Object, Move-Item, Move-ItemProperty, New-Alias, New-Event, New-FileCatalog, New-Guid, New-Item, New-ItemProperty, New-Module, New-ModuleManifest, New-Object, New-PSDrive, New-PSRoleCapabilityFile, New-PSSession, New-PSSessionConfigurationFile, New-PSSessionOption, New-PSTransportOption, New-Service, New-TemporaryFile, New-TimeSpan, New-Variable, New-WinEvent, New-WSManInstance, New-WSManSessionOption, Out-Default, Out-File, Out-Host, Out-Null, Out-String, Pop-Location, Protect-CmsMessage, Push-Location, Read-Host, Receive-Job, Receive-PSSession, Register-ArgumentCompleter, Register-EngineEvent, Register-ObjectEvent, Register-PSSessionConfiguration, Remove-Alias, Remove-Event, Remove-Item, Remove-ItemProperty, Remove-Job, Remove-Module, Remove-PSBreakpoint, Remove-PSDrive, Remove-PSSession, Remove-Service, Remove-TypeData, Remove-Variable, Remove-WSManInstance, Rename-Computer, Rename-Item, Rename-ItemProperty, Resolve-Path, Restart-Computer, Restart-Service, Resume-Service, Save-Help, Select-Object, Select-String, Select-Xml, Send-MailMessage, Set-Acl, Set-Alias, Set-AuthenticodeSignature, Set-Content, Set-Date, Set-ExecutionPolicy, Set-Item, Set-ItemProperty, Set-Location, Set-MarkdownOption, Set-PSBreakpoint, Set-PSDebug, Set-PSSessionConfiguration, Set-Service, Set-StrictMode, Set-TimeZone, Set-TraceSource, Set-Variable, Set-WSManInstance, Set-WSManQuickConfig, Show-Markdown, Sort-Object, Split-Path, Start-Job, Start-Process, Start-Service, Start-Sleep, Start-Transcript, Stop-Computer, Stop-Job, Stop-Process, Stop-Service, Stop-Transcript, Suspend-Service, Tee-Object, Test-Connection, Test-FileCatalog, Test-Json, Test-ModuleManifest, Test-Path, Test-PSSessionConfigurationFile, Test-WSMan, Trace-Command, Unblock-File, Unprotect-CmsMessage, Unregister-Event, Unregister-PSSessionConfiguration, Update-FormatData, Update-Help, Update-TypeData, Wait-Debugger, Wait-Event, Wait-Job, Wait-Process, Where-Object, Write-Debug, Write-Error, Write-Host, Write-Information, Write-Output, Write-Progress, Write-Verbose, Write-Warning, C:\Program Files\dotnet\dotnet.exe (process 24268) exited with code 0. To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops. Press any key to close this window . . . Question As you can see above in the output portion, there are no Cim cmdlets at all in the list. Why are the cmdlets in the CimCmdlets module missing? If I download PowerShell Core and look at the available cmdlets, the CimCmdlets are indeed present. How can I get access to these CimCmdlets in .NET Core? Is there a specific NuGet package I need? Thank you for the help.
I found a solution, albeit not a great one. I installed PowerShell Core 6.1.3 and copied the Microsoft.Management.Infrastructure.CimCmdlets.dll from the installation directory (C:\Program Files\PowerShell\6) into my project. If I manually import this .dll before doing anything else, then these Cim cmdlets are available. For example, in my code example in the question, replace var results = ps.AddScript("Get-Command").Invoke(); with var results = ps.AddScript("Import-Module C:\\Microsoft.Management.Infrastructure.CimCmdlets.dll; Get-Command").Invoke() And now the Cim cmdlets are available. I'd rather use a NuGet package, but this works.
this free nuget package from microsoft worked for me: https://github.com/PowerShell/MMI while it doesn't provide access to the Cim / WMIv2 powershell cmdlets, it does expose a direct api into same Cim / WMIv2 interfaces here's a sample try { using (var session = CimSession.Create(null)) { var results = session.QueryInstances(#"root\cimv2", "WQL", #"select name from win32_process where handle = 0 or handle = 4"); foreach (var result in results) { Console.WriteLine("Process name: {0}", result.CimInstanceProperties["Name"].Value); } } } catch (CimException ex) { Console.WriteLine(ex.Message); } full api documentation is available #https://learn.microsoft.com/en-us/dotnet/api/microsoft.management.infrastructure.cimsession?view=pscore-6.2.0) additional context & samples are available # https://learn.microsoft.com/en-us/windows/win32/wmisdk/enumerating-wmi#enumerating-wmi-using-c-microsoftmanagementinfrastructure
How to install Nuget Packages using ENVDTE.DTE
I created one console application to create visual studio project pragmatically, here i am not able install Nuget packages, always var componentModel = (IComponentModel)Package.GetGlobalService(typeof(SComponentModel)); statement returns null values. for your reference i added my code below. Help me to resolve this issue. static void Main(string[] args) { //InstallNuGetPackages.InstallNuGet(""); string ProjectName = "WebAPIProj"; string SolutionName = "EmptyTemplate"; System.Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.11.0"); Object obj = System.Activator.CreateInstance(type, true); EnvDTE.DTE dte = (EnvDTE.DTE)obj; dte.MainWindow.Visible = true; // optional if you want to See VS doing its thing // create a new solution dte.Solution.Create("C:\\"+ SolutionName + "\\", SolutionName); var solution = dte.Solution; // create a C# WinForms app solution.AddFromTemplate(#"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ProjectTemplatesCache\CSharp\Web\1033\EmptyWebApplicationProject40\EmptyWebApplicationProject40.vstemplate", #"C:\NewSolution\"+ ProjectName, ProjectName); InstallNuGetPackages.InstallNuGet(dte); foreach (var p in dte.Solution.Projects) { InstallNuGetPackages.InstallNuGet((Project)p, "Microsoft.AspNet.WebApi version1.1"); } // save and quit dte.ExecuteCommand("File.SaveAll"); dte.Quit(); } Code to install Nuget Packages public bool InstallNuGetPackage(Project project, string package) { bool installedPkg = true; try { var componentModel = (IComponentModel)Package.GetGlobalService(typeof(SComponentModel)); //Always this statement returns null IVsPackageInstallerServices installerServices = componentModel.GetService(); if (!installerServices.IsPackageInstalled(project, package)) { var installer = componentModel.GetService(); installer.InstallPackage(null, project, package, (System.Version)null, false); } } catch (Exception ex) { installedPkg = false; } return installedPkg; }
(Turned this into an answer for better readability and more room) created one console application - you only have access to the ServiceProvider from Visual Studio if you run your code inside of it, i.e. from an extension and/or package. Running this from a console application cannot work. Visual Studio internally does a lot more setup for all the services and general environment than creating an instance of DTE. To persue your route, although I'm not sure how feasible that is, invoke nuget.exe or NuGet.Core code to achieve similar.
Get all nuget packages in solution
I'm trying to write a unit test to enforce consolidation of Nuget packages (we have a build requirement that all unit tests pass so this would keep PRs that aren't consolidating from passing) and I was attempting to use Nuget.Core to do that. However, I cannot seem to find my way through their libraries and no one has asked this question yet. So, how can I get all the Nuget packages a given solution references programmatically?
This is the final solution (along with unit test). The key is to use the Directory library to iterate over all the projects in the solution and then use NuGet.Core to analyze the NuGet packages in each project. using Microsoft.VisualStudio.TestTools.UnitTesting; using NuGet; using Shouldly; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace UnitTests { [TestClass] public class NugetConsolidationTest { private List<string> _ignoredPackages = new List<string>(); [TestMethod] public void AllNugetPackagesAreConsolidated() { var packageVersionMapping = new Dictionary<string, List<string>>(); var parentDir = (Directory.GetParent(Directory.GetCurrentDirectory()).Parent).Parent.FullName; var files = Directory.GetFiles(parentDir, "packages.config", SearchOption.AllDirectories); foreach (var packageFile in files) { var file = new PackageReferenceFile(packageFile); var refs = file.GetPackageReferences(true); foreach (var packageRef in refs) { if (_ignoredPackages.Contains(packageRef.Id)) continue; if (!packageVersionMapping.ContainsKey(packageRef.Id)) packageVersionMapping[packageRef.Id] = new List<string>() { packageRef.Version.ToFullString() }; else { if (packageVersionMapping[packageRef.Id].All(x => !x.Equals(packageRef.Version.ToFullString(), StringComparison.InvariantCultureIgnoreCase))) packageVersionMapping[packageRef.Id].Add(packageRef.Version.ToFullString()); } } } var errors = packageVersionMapping.Where(x => x.Value.Count > 1)?. Select(x => $"Package {x.Key} has {x.Value.Count} separate versions installed! Current versions are {string.Join(", ", x.Value)}"); errors.ShouldBeEmpty(); } } }
You can always read the package.config files and parse them. The one that's inside the solution directory with reference other packages.config file is one for each project contained in the solution.
Get download link in IPackage of Nuget Core
I found example code to work with nuget api. My task is show full name and download link. Here is code: static void Main(string[] args) { //ID of the package to be looked up string packageID = "EntityFramework"; //Connect to the official package repository IPackageRepository repo = PackageRepositoryFactory.Default.CreateRepository("https://packages.nuget.org/api/v2"); //Get the list of all NuGet packages with ID 'EntityFramework' List<IPackage> packages = repo.FindPackagesById(packageID).ToList(); //Filter the list of packages that are not Release (Stable) versions packages = packages.Where(item => (item.IsReleaseVersion() == false)).ToList(); //Iterate through the list and print the full name of the pre-release packages to console foreach (IPackage p in packages) { Console.WriteLine($"{p.GetFullName()};"); } } When I debug, I see link to download, but how can I get this value? I attached screens for debug info. Debug info Missing param
You can do this to get the link to download : foreach (var p in packages.ConvertAll(o => (DataServicePackage)o)) { Console.WriteLine($"{p.GetFullName()};"); Console.WriteLine(p.DownloadUrl.ToString()) }