Carlos Torrecillas
Carlos Torrecillas

Reputation: 5736

How do I update all NuGet packages at once with the dotnet CLI?

I'm trying to update all NuGet packages for a solution in VS Code (using Mac). Is there a way to achieve that in VS code or for a specific project.json file? At the moment I'm going one by one but I would have thought there is either an extension or a feature that does that for you?

Upvotes: 88

Views: 72143

Answers (12)

MikeF
MikeF

Reputation: 1028

To list the packages you can use the dotnet cli

dotnet list package --outdated

Upvotes: 5

Jojoedevz
Jojoedevz

Reputation: 1

I upgraded "CodeGeneration.Design & CodeGeneration" versions to 6.0.16 and it worked just fine. However, netcore version is 6.

Upvotes: 0

Patrick
Patrick

Reputation: 11

You can create a simple shell script to update all the outdated NuGet packages for your solution or project. Here's a script that you can use:

#!/bin/bash

# Check if dotnet CLI is installed
if ! command -v dotnet &> /dev/null
then
    echo "dotnet CLI could not be found. Please install it and try again."
    exit 1
fi

# Function to update packages in a project
update_packages() {
    project_file=$1

    echo "Updating packages for $project_file..."

    # Get a list of outdated packages and their current versions
    outdated_packages=$(dotnet list $project_file package --outdated | awk '/>/{print $2}')

    # Check if there are any outdated packages
    if [ -z "$outdated_packages" ]; then
        echo "No outdated packages found in $project_file."
        return
    fi

    for package in $outdated_packages; do
        echo "Updating $package..."

        # Update the package to the latest version
        dotnet add $project_file package $package
    done
}

# Find all .csproj files in the current directory and subdirectories
project_files=$(find . -name "*.csproj")

for project_file in $project_files; do
    update_packages "$project_file"
done

echo "All outdated packages have been updated."

You can save in some place which are in your $PATH Variable, make it executable with chmod +x update_packages.sh, and run it in the root folder of your .NET Core solution. This script will update all outdated packages for each .csproj file found in your solution.

Upvotes: 1

Velimir
Velimir

Reputation: 762

Nukeeper seems to be an excellent tool for the job. We're even using it in nightly builds to keep the internal libraries up-to-date. After installing the tool, in the solution folder use a command like:

nukeeper update --age 0 --maxpackageupdates 1000 --change Major --useprerelease Never

Upvotes: 1

satnhak
satnhak

Reputation: 9861

UPDATE 2023/01

The current way to do this from the command line seems to be this:

https://github.com/dotnet-outdated/dotnet-outdated


OLD

This seems to work https://nukeeper.com/

dotnet tool install nukeeper --global
nukeeper update <SLN/PROJ>

UPDATE

The default settings on nukeeper seem slightly odd to me as running nukeeper update will only update a single package, and only if it is a major version that is more than 3 days old.

To update to the latest non-prerelease version of everything run:

nukeeper update -a 0 -m 1000

And for prerelease:

nukeeper update -a 0 -m 1000 --useprerelease Always

The -m 1000 flag is a synonym for everything, assuming that you have less than 1000 packages in your solution / project.

Upvotes: 14

Ali.Asadi
Ali.Asadi

Reputation: 809

For update all packages in all projects Nuget Package Manager GUI extension can do it with one click.

How it works

  1. Open your project workspace in VSCode
  2. Open the Command Palette (Ctrl+Shift+P)
  3. Select > Nuget Package Manager GUI
  4. Click Load Package Versions
  5. Click Update All Packages

test

Upvotes: 47

Dreamweaver
Dreamweaver

Reputation: 1346

For CLI - as already mentioned in comments there exist a package to perform updates https://github.com/dotnet-outdated/dotnet-outdated

From UI - In case some one is still looking for answer, with vs 2019 this has been pretty easy :)

Right Click on solution and choose "Manage nuget package for solution".

It should open a window like below -

enter image description here

On selection of package, right side we can see the project and we can update the packages :)

Upvotes: 3

Rolf Wessels
Rolf Wessels

Reputation: 847

Based on Jon Canning's powershell solution. I fixed a small bug where only the first dependency was being updated and not all the dependencies for the project file.

$regex = 'PackageReference Include="([^"]*)" Version="([^"]*)"'

ForEach ($file in get-childitem . -recurse | where {$_.extension -like "*proj"})
{
    $packages = Get-Content $file.FullName |
        select-string -pattern $regex -AllMatches | 
        ForEach-Object {$_.Matches} | 
        ForEach-Object {$_.Groups[1].Value.ToString()}| 
        sort -Unique
    
    ForEach ($package in $packages)
    {
        write-host "Update $file package :$package"  -foreground 'magenta'
        $fullName = $file.FullName
        iex "dotnet add $fullName package $package"
    }
}

Upvotes: 23

Jon Canning
Jon Canning

Reputation: 1642

Here's a shell script and a powershell script that will do this

#!/bin/bash
regex='PackageReference Include="([^"]*)" Version="([^"]*)"'
find . -name "*.*proj" | while read proj
do
  while read line
  do
    if [[ $line =~ $regex ]]
    then
      name="${BASH_REMATCH[1]}"
      version="${BASH_REMATCH[2]}"
      if [[ $version != *-* ]]
      then
        dotnet add $proj package $name
      fi
    fi
  done < $proj
done

$regex = [regex] 'PackageReference Include="([^"]*)" Version="([^"]*)"'
ForEach ($file in get-childitem . -recurse | where {$_.extension -like "*proj"})
{
  $proj = $file.fullname
  $content = Get-Content $proj
  $match = $regex.Match($content)
  if ($match.Success) {
    $name = $match.Groups[1].Value
    $version = $match.Groups[2].Value
    if ($version -notin "-") {
      iex "dotnet add $proj package $name"
    }
  }
}

Should also mention Paket as a fantastic alternative package manager that supports update:

https://fsprojects.github.io/Paket/index.html

dotnet tool install paket --tool-path .paket

Also have a look at dotnet outdated: https://github.com/dotnet-outdated/dotnet-outdated

Upvotes: 20

agua from mars
agua from mars

Reputation: 17434

I wrote this powershell script to keep packages up to date on Githup.
To update all packages of the solution I use first dotnet sln list.
The for each project I get the list of outdated package with dotnet list package --outdated, it give the latest version of each outdated packages.
And for each packages I update the project with dotnet add package {package name} --version {new version}.

Full code:

# Update one project packages
function UpdatePackages {
    param (
        $project
    )

    $return = $false
    
    # Get outdated packages
    $packageLineList = dotnet list $project package --outdated
    
    foreach($line in $packageLineList) {
       Write-Host $line
       
       $match = $line -match '>\s(\S*)\s*\S*\s*\S*\s*(\S*)'
       if (!$match) {
          # the line doesn't contain a package information, continue
          continue
       }
       
       # update an outdated package
       $added = dotnet add $project package $Matches.1 --version $Matches.2

       if ($LASTEXITCODE -ne 0) {
           # error while updating the package
           Write-Error "dotnet add $project package $Matches.1 --version $Matches.2 exit with code $LASTEXITCODE"
           Write-Host $added
           break
       }

       $return = $true
    }

    return $return
}

# Restore dependencies
dotnet restore

# Get all project list in the solution
$projectList = dotnet sln list
$updated = $false

foreach($path in $projectList) {
    if ($path -eq "Project(s)" -or $path -eq "----------") {
        # The line doesn't contain a path, continue
        continue
    }

    # Update project dependencies
    $projectUpdated = UpdatePackages -project $path
        
    if ($LASTEXITCODE -ne 0) {
        #The update fail, exit
        exit $LASTEXITCODE
    }

    $updated = $updated -or $projectUpdated
}

if (!$updated) {
    # No packages to update found, exit
    Write-Host "nothing to update"
    exit 0
}

Upvotes: 2

Roemer
Roemer

Reputation: 2271

I created a cake build task to do the same. See below:

Task("Nuget-Update")
    .Does(() =>
{
    var files = GetFiles("./**/*.csproj");
    foreach(var file in files)
    {
        var content = System.IO.File.ReadAllText(file.FullPath);
        var matches = System.Text.RegularExpressions.Regex.Matches(content, @"PackageReference Include=""([^""]*)"" Version=""([^""]*)""");
        Information($"Updating {matches.Count} reference(s) from {file.GetFilename()}");
        foreach (System.Text.RegularExpressions.Match match in matches) {
            var packageName = match.Groups[1].Value;
            Information($"  Updating package {packageName}");
            var exitCode = StartProcess("cmd.exe",
                new ProcessSettings {
                    Arguments = new ProcessArgumentBuilder()
                        .Append("/C")
                        .Append("dotnet")
                        .Append("add")
                        .Append(file.FullPath)
                        .Append("package")
                        .Append(packageName)
                }
            );
        }
    }
});

Upvotes: 0

Boudin
Boudin

Reputation: 61

Based on Jon Caning answer, I've written this small bash script to add in .bashrc (or just change a bit to keep it in its bash file)

function read_solution() {
    echo "Parsing solution $1"

    while IFS='' read -r line || [[ -n "$line" ]]; do
            if [[ $line =~ \"([^\"]*.csproj)\" ]]; then
                    project="${BASH_REMATCH[1]}"

                    read_project "$(echo "$project"|tr '\\' '/')"
            fi
    done < "$1"
}

function read_project() {
    echo "Parsing project $1"
    package_regex='PackageReference Include="([^"]*)" Version="([^"]*)"'

    while IFS='' read -r line || [[ -n "$line" ]]; do
            if [[ $line =~ $package_regex ]]; then
                    name="${BASH_REMATCH[1]}"
                    version="${BASH_REMATCH[2]}"

                    if [[ $version != *-* ]]; then
                            dotnet add "$1" package "$name"
                    fi
            fi
    done < $1
}

function dotnet_update_packages() {
    has_read=0

    if [[ $1 =~ \.sln$ ]]; then
            read_solution "$1"
            return 0
    elif [[ $1 =~ \.csproj$ ]]; then
            read_project "$1"
            return 0
    elif [[ $1 != "" ]]; then
            echo "Invalid file $1"
            return 1
    fi


    for solution in ./*.sln; do
            if [ ! -f ${solution} ]; then
                    continue
            fi

            read_solution "${solution}"
            has_read=1
    done

    if [[ $has_read -eq 1 ]]; then
            return 0
    fi

    for project in ./*.csproj; do
            if [ ! -f ${project} ]; then
                    continue
            fi

            read_project "${project}"
    done
}
export -f dotnet_update_packages

To use it, either run it without parameter in a folder with a solution, it would first look for all solution files in the current folder and run for all csproj files referenced in those (it might need to be changed if you work with something else than c#).

If no solution is found, it looks for all csproj files in the current directory and run for those.

You can also pass a .sln or .csproj file as argument:
dotnet_update_packages mysolution.sln
dotnet_update_packages myproject.csproj

I'm not a bash expert so I'm sure it can be improved

Upvotes: 1

Related Questions