【问题标题】:How do I update all NuGet packages at once with the dotnet CLI?如何使用 dotnet CLI 一次更新所有 NuGet 包?
【发布时间】:2017-04-26 03:10:28
【问题描述】:

我正在尝试为 VS Code 中的解决方案更新所有 NuGet 包(使用 Mac)。有没有办法在 VS 代码或特定的 project.json 文件中实现这一点?目前我将一一进行,但我会认为有一个扩展或功能可以为您做到这一点?

【问题讨论】:

标签: nuget visual-studio-code .net-core


【解决方案1】:

对于更新所有项目中的所有包nuget package manager gui扩展可以一键完成。

工作原理

  1. 在 VSCode 中打开您的项目工作区
  2. 打开命令面板 (Ctrl+Shift+P)
  3. 选择 > Nuget 包管理器 GUI
  4. 点击Load Package Versions
  5. 点击Update All Packages

【讨论】:

  • 这真的很酷 - 但一个问题是,当它更新包时,它会更改它修改的 csproj 文件的格式,f.ex。删除空行并更改缩进。
  • 您可以在设置中设置自己的缩进://用于缩进XML输出的空格数。像 ' ' 或 '\t' 这样的传递字符也被接受 "nugetpackagemanagergui.indentType": "2"
  • 伟大的扩展!您是否打算发布新版本?
  • 很遗憾,这些天我太忙了。但我已经得到了一些反馈,我会在未来改进它。
【解决方案2】:

基于 Jon Canning 的 powershell 解决方案。我修复了一个小错误,它只更新了第一个依赖项,而不是项目文件的所有依赖项。

$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"
    }
}

【讨论】:

    【解决方案3】:

    这里有一个 shell 脚本和一个 powershell 脚本可以做到这一点

    #!/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"
        }
      }
    }
    

    还应该提到 Paket 作为支持更新的出色替代包管理器:

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

    dotnet tool install paket --tool-path .paket

    也可以看看dotnet outdatedhttps://github.com/dotnet-outdated/dotnet-outdated

    【讨论】:

    • 看起来 powershell 脚本只返回每个文件的第一个正则表达式匹配。我将在下面添加一个替代解决方案。
    • shell 脚本很棒!
    • 不更新版本号中带有破折号的软件包的原因是什么? (如果我是这样读的……)
    【解决方案4】:

    这似乎工作https://nukeeper.com/

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

    更新

    nukeeper 上的默认设置对我来说似乎有点奇怪,因为运行 nukeeper update 只会更新一个包,并且只有当它是超过 3 天的主要版本时。

    要更新到所有运行的最新非预发布版本:

    nukeeper update -a 0 -m 1000
    

    对于预发布:

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

    -m 1000 标志是一切的同义词,假设您的解决方案/项目中的包少于 1000 个。

    【讨论】:

    • 很棒的工具!希望我在今天之前知道这件事。我使用了上面的 bash 脚本,虽然效果很好,但我喜欢我可以使用这个工具获得统计数据
    【解决方案5】:

    我写了this powershell script 以使软件包在 Githup 上保持最新。
    要更新解决方案的所有软件包,我首先使用dotnet sln list
    对于每个项目,我都使用dotnet list package --outdated 获得过时软件包列表,它提供了每个过时软件包的最新版本。
    对于每个包,我都会使用 dotnet add package {package name} --version {new version} 更新项目。

    完整代码:

    # 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
    }
    

    【讨论】:

      【解决方案6】:

      对于 CLI - 正如在 cmets 中已经提到的,存在一个执行更新的包 https://github.com/dotnet-outdated/dotnet-outdated

      从用户界面 - 如果有人仍在寻找答案,与 2019 年相比,这很容易:)

      右键单击解决方案并选择“Manage nuget package for solution”。

      它应该会打开一个如下所示的窗口 -

      在选择包时,右侧我们可以看到项目,我们可以更新包:)

      【讨论】:

      • 如果不清楚,如果您单击最顶部的菜单条“更新”,您可以一键选择整个解决方案的所有可用更新包...无需从中选择右侧的详细信息窗口。
      【解决方案7】:

      根据 Jon Caning 的回答,我编写了这个小 bash 脚本以添加到 .bashrc 中(或者只是稍作更改以将其保留在其 bash 文件中)

      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
      

      要使用它,要么在带有解决方案的文件夹中不带参数运行它,它会首先在当前文件夹中查找所有解决方案文件并运行其中引用的所有 csproj 文件(如果你工作,可能需要更改它用 c# 以外的东西)。

      如果没有找到解决方案,它会查找当前目录中的所有 csproj 文件并运行。

      您也可以将 .sln 或 .csproj 文件作为参数传递:
      dotnet_update_packages mysolution.sln
      dotnet_update_packages myproject.csproj

      我不是 bash 专家,所以我确信它可以改进

      【讨论】:

        【解决方案8】:

        Nukeeper 似乎是完成这项工作的绝佳工具。我们甚至在夜间构建中使用它来保持内部库是最新的。安装工具后,在解决方案文件夹中使用如下命令:

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

        【讨论】:

          【解决方案9】:

          我创建了一个蛋糕制作任务来做同样的事情。见下文:

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

          【讨论】:

            猜你喜欢
            • 2022-10-13
            • 2017-07-01
            • 2020-06-30
            • 2019-12-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-09-30
            • 2016-02-06
            相关资源
            最近更新 更多