43

To keep our house in order, I want to automatically assemble licenses for project dependencies in our documentation, rather than having to add them manually.

Does anybody know a simple way to traverse programmatically a set of CSPROJ files and extract the license information for the referenced packages as a link or string?

mguassa
  • 697
  • 5
  • 14
Byron Ross
  • 627
  • 1
  • 5
  • 8
  • When you say licence information you mean a short string representing the licence type or a link pointing to the licence page on the web? How would you like this information to be returned, in a console window or, for example, in a CSV/HTML file? – mguassa Jun 14 '15 at 20:01
  • I could take either the link or a string. I'm more looking for a programmatic way to access the information in the first place – Byron Ross Jun 16 '15 at 13:58

4 Answers4

46

One way I know to get such information is by using PowerShell in the Package Manager Console, from within Visual Studio.

The Package Manager Console is a PowerShell console within Visual Studio used to interact with NuGet and automate Visual Studio.

Basically you can use the Get-Package cmdlet to get a list of packages referenced in a specific project (or in an entire Solution). Regarding the license information for each package, for what I've seen you can only get the license URL and not just a short string representing the license type.

Here's an example for a Solution of mine returning a list of entries, each one consisting of the package identifier and the link to the license:

Get-Package | Select-Object Id,LicenseUrl

The output is something like this:

get-package output

Other elements that can be returned are documented in the Nuspec reference, in the metadata section (e.g. the version of the package, a short description, etc.).

mguassa
  • 697
  • 5
  • 14
10

Based on multiple sources, I've made a PowerShell script that reads all NuGet packages and fetches the license files and put that in a folder called "licenses". The script should be run on the root of the project (where the "packages" folder is located).

# Run in Package Manager Console with `./download-packages-license.ps1`.
# If access denied, execute `Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned`.

Split-Path -parent $dte.Solution.FileName | cd; New-Item -ItemType Directory -Force -Path ".\licenses";
@( Get-Project -All | ? { $_.ProjectName } | % {
    Get-Package -ProjectName $_.ProjectName | ? { $_.LicenseUrl }
} ) | Sort-Object Id -Unique | % {
    $pkg = $_;
    Try {
        if ($pkg.Id -notlike 'microsoft*' -and $pkg.LicenseUrl.StartsWith('http')) {
            Write-Host ("Download license for package " + $pkg.Id + " from " + $pkg.LicenseUrl);
            #Write-Host (ConvertTo-Json ($pkg));

            $licenseUrl = $pkg.LicenseUrl
            if ($licenseUrl.contains('github.com')) {
                $licenseUrl = $licenseUrl.replace("/blob/", "/raw/")
            }

            $extension = ".txt"
            if ($licenseUrl.EndsWith(".md")) {
                $extension = ".md"
            }

            (New-Object System.Net.WebClient).DownloadFile($licenseUrl, (Join-Path (pwd) 'licenses\') + $pkg.Id + $extension);
        }
    }
    Catch [system.exception] {
        Write-Host ("Could not download license for " + $pkg.Id)
    }
}

Disclaimer: I'm no PowerShell expert. Run at your own risk :)

I couldn't find any simple code that detects which license the NuGet package has, based on it's license file. The only project that comes close to a solution is Licensee, but this is build in Ruby.

jerone
  • 211
  • 2
  • 6
  • The "packages" folder is not used for modern solutions using `PackageReference`. It seems your answer doesn't require this folder - you may want to write something like "where the sln file is located). – Patrick Stalph Feb 06 '20 at 07:43
  • 1
    Unfortunately, most license URLs now point to HTML-only versions (early 2020). For example, https://licenses.nuget.org/ ignores any "Accept: text/plain" (or json) headers and returns html regardless. – Patrick Stalph Feb 06 '20 at 08:03
  • @dominic-cerquetti Maybe you can post your changes in your own answer. They look useful. – jerone May 18 '21 at 08:00
1

I managed to get the licence information using the following command:

@( @(Get-Project -All | ForEach-Object { Get-Package -ProjectName $_.ProjectName }) | Select Id -Unique ) | ForEach-Object { $pkg = $_ ;$pkgId = $_.Id ; if ($pkgId -notlike  'microsoft*'){ $url = Open-PackagePage $pkgId -License -WhatIf -PassThru; Write-Host "$pkgId $url"}}
  • 2
    Unfortunately this no longer works, as `Open-PackagePage` is [now deprecated](https://docs.microsoft.com/en-us/nuget/reference/ps-reference/ps-ref-open-packagepage) – sfuqua Apr 22 '21 at 17:16
1

There is now a project called "Nuget License Utility" for .NET:

A .net core tool to print the licenses of a project. This tool support .NET Core and .NET Standard Projects.

jerone
  • 211
  • 2
  • 6