I am working on tool where I need to programmatically identify Nuget package which is added as PackageReference in my current project is a metapackage or regular package. Since there is not enough documentation around Nuget V3 APIs, finding it hard to get those details. Any pointers in this regard are appreciated.
I tried following code and method GetMetadataAsync returns collection of NuGet.Protocol.PackageSearchMetadata type however there isn't any property on this type which says package is metapackage.
private async void button1_Click(object sender, EventArgs e)
{
ILogger log = new Logger();
List<Lazy<NuGet.Protocol.Core.Types.INuGetResourceProvider>> providers = new List<Lazy<NuGet.Protocol.Core.Types.INuGetResourceProvider>>();
providers.AddRange(Repository.Provider.GetCoreV3());
PackageSource packageSource = new PackageSource("https://api.nuget.org/v3/index.json");
SourceRepository sourceRepository = new SourceRepository(packageSource, providers);
PackageMetadataResource packageMetadataResource = await sourceRepository.GetResourceAsync<PackageMetadataResource>();
IEnumerable<IPackageSearchMetadata> searchMetadata = await packageMetadataResource.GetMetadataAsync("Microsoft.AspNetCore.All", true, true,log, CancellationToken.None);
var list = searchMetadata.ToList();
}
A "metapackage" is more a convention for constructing a nuget package than an actual "type" / "property" on a package.
If a NuGet package doesn't contain any assets (libraries, content assets, tools, build logic etc.) - practically empty - but only has dependencies on other packages, it is referred to as "metapackage". The only way to test if a package fulfils this definition is to download and inspect its assets.
Related
For context, I'm building an application that needs to download/unpack packages and their dependencies from arbitrary package sources (including the public gallery by default) and upgrade those packages to the latest version when requested. There are no project.json files or similar, it's all code driven. It's not a particularly complicated use case and didn't require too much code in the v2 APIs.
In v3 however, I can't figure out how to correctly interact with the local package store. For example, the FolderNuGetProject class that I would have thought lists all the packages on disk at a given location in FolderNuGetProject.GetInstalledPackagesAsync() just returns an empty enumerable. To make matters more confusing, FolderNuGetProject.PackageExists() actually does return whether the package exists on disk, which means GetInstalledPackagesAsync() and PackageExists() appear to be inconsistent.
None of the other NuGetProject derivatives appear related to the file system. Is there some other way of listing the packages that have been installed into a particular folder? If I need to create my own NuGetProject (and I'm hoping I don't), are there any methods that will help with parsing NuGet-generated folder names into package IDs and versions, or is the only reliable way of getting the ID and version to open the nuspec (and are there any easy to find methods for that)?
One interpretation of why this isn't working as I expect is that NuGetProject.GetInstalledPackagesAsync() isn't actually intended to get the installed packages (I.e., those that have been downloaded and unpacked), but rather those that have been declared in whatever project system is in use. For example, the BuildIntegratedNuGetProject class appears to return package references for the packages in the project.json, regardless of their status on disk. That would also explain why FolderNuGetProject just returns an empty enumerable, because there are no "declared" packages if you're just looking at the local repository.
TL;DR: What is the best way to crawl the local package store and get the packages and versions that are present there?
(this was also issue #2664 on the NuGet GitHub project, but was moved here by request)
Introduction
I have the same question and I looked your post on GitHub, Google and here. I try a lot of things to find the local packages.
I found some solutions, but I don't know if it's the best way to do it.
I posted a question about local packages too, because I can list all local packages, but I can't have the AssemblyReferences property (dll).
Code example
var rootPath = #"pathWhereNuGetPackagesAre";
var logger = new Logger();
List<Lazy<INuGetResourceProvider>> providers = new List<Lazy<INuGetResourceProvider>>();
providers.AddRange(Repository.Provider.GetCoreV3());
FindLocalPackagesResourceV2 findLocalPackagev2 = new FindLocalPackagesResourceV2(rootPath);
var packageFound = findLocalPackagev2.GetPackages(logger, CancellationToken.None).FirstOrDefault();
//found, but missing a lot of informations...
var supportedFramework = new[] { ".NETFramework,Version=v4.6" };
var searchFilter = new SearchFilter(true)
{
SupportedFrameworks = supportedFramework,
IncludeDelisted = false
};
// The trick here is to put the local nuget path, not using the URL : https://api.nuget.org/v3/index.json
PackageSource localSource = new PackageSource(rootPath);
SourceRepository localRepository = new SourceRepository(localSource, providers);
PackageSearchResource searchLocalResource = await localRepository
.GetResourceAsync<PackageSearchResource>();
var packageFound3 = await searchLocalResource
.SearchAsync("Newtonsoft.Json", searchFilter, 0, 10, logger, CancellationToken.None);
var thePackage = packageFound3.FirstOrDefault();
// found but missing the assemblies property
public class Logger : ILogger
{
private List<string> logs = new List<string>();
public void LogDebug(string data)
{
logs.Add(data);
}
public void LogVerbose(string data)
{
logs.Add(data);
}
public void LogInformation(string data)
{
logs.Add(data);
}
public void LogMinimal(string data)
{
logs.Add(data);
}
public void LogWarning(string data)
{
logs.Add(data);
}
public void LogError(string data)
{
logs.Add(data);
}
public void LogInformationSummary(string data)
{
logs.Add(data);
}
public void LogErrorSummary(string data)
{
logs.Add(data);
}
}
Hope this will help!
In Visual Studio, Open package manager console.
List local (installed) packages use following command.
Get-Package
You can list all available packages on feed with following command
Get-Package -ListAvailable
If this commands are not working, check "Packege Manager Settings"->"Package Source" and confirm nuget feed configured correctly. (If you dont see your feed URL, You should add your feed there.) for details: Consume nuget package from VS
You can also check nuget feed configuration from this file
C:\Users{{user}}\AppData\Roaming\NuGet\NuGet.config
for more details about nuget config file: nuget config file
Also, Local nuget packages should ve stored at this path
C:\Users{{user}}.nuget\packages
I want to use MediaToolkit from Nuget Package Manager and in my test projects, the tool worked fine in VB.NET and C#.NET project. However, when I use it in my real project (which has been upgraded many times to higher version in VB.NET), I am always receiving an error attached screenshot. In my test project and real project, both are in .NET 4.6.
string videoPath = Server.MapPath("~/Video/" + fileUpload.FileName);
var inputVideoFile = new MediaFile { Filename = videoPath };
using (var engine = new Engine())
{
engine.GetMetadata(inputVideoFile);
}
duration = inputVideoFile.Metadata.Duration;
Could you please help me to resolve the issue?
I want to include Stanford CoreNLP in my Unity3D project. I included CoreNLP from Nuget and downloaded the NLP models from CoreNLP. Then I copied the NLP model folder into the project -> bin -> Debug folder.
The code looks like this:
var jarRoot = #"stanford-corenlp-3.9.1-models\";
const string text = "Kosgi Santosh sent an email to Stanford University. He didn't get a reply.";
var props = new Properties();
props.setProperty("annotators", "tokenize, ssplit, pos, lemma, ner, parse, dcoref");
props.setProperty("sutime.binders", "0");
var curDir = Environment.CurrentDirectory;
Directory.SetCurrentDirectory(jarRoot);
var pipeline = new StanfordCoreNLP(props);
Directory.SetCurrentDirectory(curDir);
// Annotation
var annotation = new Annotation(text);
pipeline.annotate(annotation);
var sentences = annotation.get(typeof(CoreAnnotations.SentencesAnnotation));
if (sentences == null)
{
return;
}
foreach (Annotation sentence in sentences as ArrayList)
{
System.Console.WriteLine(sentence);
}
After running, I only got some Error info
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for
further details.
I searched SLF4J site however the solution only applies to Java project. How do I supposed to solve this in my C# project?
First, go to the Visual Studio (I have VS 2017). Then go to the Tools menu and select NuGet Package Manager->Package Manager Console. The Package Manager Console will appear. Type this command: Install-Package slf4j-NetCommonLogging -Version 1.7.5.4 and press Enter key. The VS will install slf4j-NetCommonLogging dll file for your project and it will run correctly without any errors or warnings. Enjoy.
What's the best way to read (ideally via C#) the packages listed in packages.config files?
Within our source code repository I have a lot of solutions and projects and equally a lot of packages.config files. I'm trying to build a consolidated list of packages (and versions) in use across my source code repository.
I can see there is a NuGet.Core package available - how could I use this to achieve my goal?
Thanks
If you do not want to read the XML directly you can install the NuGet.Core NuGet package and then use the PackageReference class.
Here is some example code that uses this class to print out the package id and its version.
string fileName = #"c:\full\path\to\packages.config";
var file = new PackageReferenceFile(fileName);
foreach (PackageReference packageReference in file.GetPackageReferences())
{
Console.WriteLine("Id={0}, Version={1}", packageReference.Id, packageReference.Version);
}
You will need to find the packages.config files yourself which you can probably do with a directory search, something like:
foreach (string fileName in Directory.EnumerateFiles("d:\root\path", "packages.config", SearchOption.AllDirectories))
{
// Read the packages.config file...
}
An alternative and more up to date way of doing this is to install the NuGet.Packaging NuGet package and use code similar to:
var document = XDocument.Load (fileName);
var reader = new PackagesConfigReader (document);
foreach (PackageReference package in reader.GetPackages ())
{
Console.WriteLine (package.PackageIdentity);
}
As suggested you will need to install NuGet.Core, your solution may have several projects in it, so it's good to know how to specify the project name when installing. Let's say your Solution is MySolution and you have two projects Project01 & Project02 and you only want to install in Project02.
Install-Package NuGet.Core -ProjectName Project02
Next you will need to add a using statement in the whatever.cs page you are going to do your work to target the package and let's say you just want to get the version number so that you can print it out somewhere on your website. That is actually what I wanted to do.
using NuGet;
next I wanted to get at a specific package and read it's version number so that when we release my software I have a visual identifier at a certain place on my website that I can go to and see the version that is in production.
here is the code I wrote to populate a webforms label on my page.
protected void Page_Load(Object sender, EventArgs e)
{
var pkgRefpath = Server.MapPath("~/packages.config");
PackageReferenceFile nugetPkgConfig = new PackageReferenceFile(pkgRefpath);
IEnumerable<PackageReference> allPackages = nugetPkgConfig.GetPackageReferences();
var newtonsoftPkg = (
from pkg in allPackages
where pkg.Id == "Newtonsoft.Json"
select pkg
).FirstOrDefault();
if (newtonsoftPkg== null) return;
var newtonsoftPkg_Version = newtonsoftPkg.Version;
ltrNewtonsoftVer.Text = newtonsoftPkg_Version.ToString();
}
This is a slightly different answer to the question, but this shows the solution that I ended up with for my needs after finding this Question/Answer and modifying what I learned to suit my own needs. I hope it can help someone else out.
I have a bunch of small C# projects which use a couple of NuGet packages. I'd like to be able to update version of a given package automatically. More then that: I'd like to be warned if a project uses different version from the others.
How do I enforce same version dependency across multiple C# projects?
As I haven't found another way to enforce this, I've written a unit test which will fail if different package versions are being found in any packages.config in any subfolder.
As this might be useful for others, you'll find the code below. You'll have to adapt the resolution of the root folder done in GetBackendDirectoryPath().
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using NUnit.Framework;
namespace Base.Test.Unit
{
[TestFixture]
public class NugetTest
{
private const string PACKAGES_CONFIG_FILE_NAME = "packages.config";
private const string BACKEND_DIRECTORY_NAME = "DeviceCloud/";
private const string PACKAGES_NODE_NAME = "packages";
private const string PACKAGE_ID_ATTRIBUTE_NAME = "id";
private const string PACKAGE_VERSION_ATTRIBUTE_NAME = "version";
/// <summary>
/// Tests that all referenced nuget packages have the same version by doing:
/// - Get all packages.config files contained in the backend
/// - Retrieve the id and version of all packages
/// - Fail this test if any referenced package has referenced to more than one version accross projects
/// - Output a message mentioning the different versions for each package
/// </summary>
[Test]
public void EnforceCoherentReferences()
{
// Act
IDictionary<string, ICollection<PackageVersionItem>> packageVersionsById = new Dictionary<string, ICollection<PackageVersionItem>>();
foreach (string packagesConfigFilePath in GetAllPackagesConfigFilePaths())
{
var doc = new XmlDocument();
doc.Load(packagesConfigFilePath);
XmlNode packagesNode = doc.SelectSingleNode(PACKAGES_NODE_NAME);
if (packagesNode != null && packagesNode.HasChildNodes)
{
foreach (var packageNode in packagesNode.ChildNodes.Cast<XmlNode>())
{
if (packageNode.Attributes == null)
{
continue;
}
string packageId = packageNode.Attributes[PACKAGE_ID_ATTRIBUTE_NAME].Value;
string packageVersion = packageNode.Attributes[PACKAGE_VERSION_ATTRIBUTE_NAME].Value;
if (!packageVersionsById.TryGetValue(packageId, out ICollection<PackageVersionItem> packageVersions))
{
packageVersions = new List<PackageVersionItem>();
packageVersionsById.Add(packageId, packageVersions);
}
//if (!packageVersions.Contains(packageVersion))
if(!packageVersions.Any(o=>o.Version.Equals(packageVersion)))
{
packageVersions.Add(new PackageVersionItem()
{
SourceFile = packagesConfigFilePath,
Version = packageVersion
});
}
if (packageVersions.Count > 1)
{
//breakpoint to examine package source
}
}
}
}
List<KeyValuePair<string, ICollection<PackageVersionItem>>> packagesWithIncoherentVersions = packageVersionsById.Where(kv => kv.Value.Count > 1).ToList();
// Assert
string errorMessage = string.Empty;
if (packagesWithIncoherentVersions.Any())
{
errorMessage = $"Some referenced packages have incoherent versions. Please fix them by adapting the nuget reference:{Environment.NewLine}";
foreach (var packagesWithIncoherentVersion in packagesWithIncoherentVersions)
{
string packageName = packagesWithIncoherentVersion.Key;
string packageVersions = string.Join("\n ", packagesWithIncoherentVersion.Value);
errorMessage += $"{packageName}:\n {packageVersions}\n\n";
}
}
Assert.IsTrue(packagesWithIncoherentVersions.Count == 0,errorMessage);
//Assert.IsEmpty(packagesWithIncoherentVersions, errorMessage);
}
private static IEnumerable<string> GetAllPackagesConfigFilePaths()
{
return Directory.GetFiles(GetBackendDirectoryPath(), PACKAGES_CONFIG_FILE_NAME, SearchOption.AllDirectories)
.Where(o=>!o.Contains(".nuget"));
}
private static string GetBackendDirectoryPath()
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
var uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path.Substring(0, path.IndexOf(BACKEND_DIRECTORY_NAME, StringComparison.Ordinal) + BACKEND_DIRECTORY_NAME.Length));
}
}
public class PackageVersionItem
{
public string SourceFile { get; set; }
public string Version { get; set; }
public override string ToString()
{
return $"{Version} in {SourceFile}";
}
}
}
I believe I have found a setup which solves this (and many other) problem(s).
I just realized one can use a folder as nuget source. Here is what I did:
root
+ localnuget
+ Newtonsoft.Json.6.0.1.nupkg
+ nuget.config
+ packages
+ Newtonsoft.Json.6.0.1
+ src
+ project1
nuget.config looks like this:
<configuration>
<config>
<add key="repositoryPath" value="packages" />
</config>
<packageSources>
<add key="local source" value="localnuget">
</packageSources>
</configuration>
You can add Nuget server to nuget.config to get access to updates or new dependencies during development time:
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
Once you're done, you can copy .nupkg from cache to localnuget folder to check it in.
There are 3 things I LOVE about this setup:
I'm now able to use Nuget features, such as adding props and targets. If you have a code generator (e.g. protobuf or thrift) this becomes pricesless.
It (partially) solves the problem of Visual Studio not copying all DLLs, because you need to specify dependencies in .nuspec file and nuget loads indirect dependencies automatically.
I used to have a single solution file for all projects so updating nuget packages was easier. I haven't tried yet but I think I solved that problem too. I can have nuget packages for the project I want to export from a given solution.
I don't know how to enforce it, but I've found the "Consolidate" tab to help.
This tab shows you packages that have different versions throughout the solution. From there you can select projects and use the install button to install the same package version across them. This tab can be found under "Manage NuGet for solution".
See Consolidate tab in Microsoft documentation.
Thank you for asking this - so I am not alone. I put considerable time into ensuring all projects in my solution use the same package version. The NuGet user interface (and also the command line interface) also contribues to having different versions among the projects within a solution. In particular when a new project is added to the solution and package X shall be added to the new project, NuGet is overly greedy to download the latest version from nuget.org instead of using the local version first, which would be the better default handling.
I completely agree with you, that NuGet should warn if different versions of a package are used within a solution. And it should help avoiding this and fixing such version maze.
The best I found to do now is to enumerate all packages.config files within the solution folder (your projects-root) which look like
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net451" />
...
</packages>
then sorting the xml-nodes by id and analysing the version numbers.
If any package occurs with different version numbers, making them all equal and afterwards running the NuGet command
Update-Package -ProjectName 'acme.lab.project' -Reinstall
should fix wrong package versions.
(Since NuGet is open source it would certainly be a cool thing to get our hands dirty and implement the missing version-conflict avoidance utility.)
Additionally to the "Consolidate" tab in VS, you can use powershell Sync-Package
https://learn.microsoft.com/en-us/nuget/reference/ps-reference/ps-ref-sync-package.
Examples:
# Sync the Elmah package installed in the default project into the other projects in the solution
Sync-Package Elmah
# Sync the Elmah package installed in the ClassLibrary1 project into other projects in the solution
Sync-Package Elmah -ProjectName ClassLibrary1
# Sync Microsoft.Aspnet.package but not its dependencies into the other projects in the solution
Sync-Package Microsoft.Aspnet.Mvc -IgnoreDependencies
# Sync jQuery.Validation and install the highest version of jQuery (a dependency) from the package source
Sync-Package jQuery.Validation -DependencyVersion highest