【问题标题】:Get a list of all NuGet packages used in a solution获取解决方案中使用的所有 NuGet 包的列表
【发布时间】:2021-03-18 21:24:09
【问题描述】:

我正在寻找一种方法来使用命令行脚本而不是在 Visual Studio 中手动获取解决方案(特别是版本)中每个项目中所有使用的 NuGet 包的列表。

使用带有命令“Get-Package”的包管理器控制台给了我我想要的东西,但它在 VS 之外不可用。

我使用的是本地 NuGet 提要。 我的默认包管理格式是 PackageReference。

任何想法都会有所帮助

【问题讨论】:

  • 你不能从项目文件中读取它们吗?
  • 它们在每个项目的纯文本 packages.config 中明确列出。通常有关于项目文件中包位置的提示,但 Nuget 包还原使用 packages.config。
  • @JeffDavies 感谢您的回答。我有一个包含 150 多个项目的解决方案。所以搜索它对我来说可能不是最好的解决方案,但这会起作用。谢谢!
  • @Avihay,这个powershell命令将列出所有packages.configs:Get-ChildItem -Path $path -Recurse -Filter "packages.config" |选择全名。我对 powershell 的精通不足以从这个列表中查找文件的内容。可以在 Bash 中轻松完成。

标签: c# nuget


【解决方案1】:

PackageReference 作为一种包管理格式仅适用于每个项目。 所以你需要单独“分析”每个项目。

从命令行,“将”有一种方法可以列出所有的包。 这是“dotnet list package”命令。 我说会,因为它仍在预览中。 您可以从here 下载 2.2.100 版本。 相关spec

最简单的使用例子是:

dotnet list YourSln.sln package

如果您不想使用 dotnet.exe 预览,您可以考虑编写自己的工具,通过读取每个项目的资产文件,这是实际命令所做的。 参考代码herehere

【讨论】:

  • 这仅适用于 .NET Core 和 .NET 5.0。
  • 它适用于基于 SDK 的项目。目标框架和工具之间存在差异。这是一个工具功能,因此与 .NET 5.0 没有真正的关系。它适用于基于 SDK 的项目,这些项目的目标不仅仅是 .NET Core。
【解决方案2】:

在 Visual Studio 的包管理器控制台中运行此命令 Get-Package | Select-Object Id, Version, LicenseUrl, ProjectName。取自这个答案:https://softwareengineering.stackexchange.com/a/286981

【讨论】:

    【解决方案3】:

    我确信有更好的方法可以做到这一点,但在使用 PackageReferences 时,这里有一个全面的 PowerShell 方法:

    Get-Content .\<solution>.sln | where { $_ -match "Project.+, ""(.+)""," } | foreach { $matches[1] } | % {Get-Content $_ | Find "<PackageReference Include" } | Sort-Object -Unique
    

    在 .sln 所在的文件夹中运行它

    它产生这样的输出:

    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.5.0" />
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.4" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.1" />
    <PackageReference Include="Microsoft.Extensions.Http" Version="2.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
    <PackageReference Include="Microsoft.Extensions.Options" Version="2.1.1" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.5" />
    <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
    <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
    

    我故意删除重复项;如果您愿意,可以省略该部分。

    在我的情况下,这与来自 Get-Package 的输出匹配,但一个例外是 Microsoft.NETCore.App,因为它没有在任何地方列为依赖项,但可能是从 &lt;TargetFramework&gt;netcoreapp2.1&lt;/TargetFramework&gt; 派生的。

    【讨论】:

    • 好主意。但由于某种原因,它没有显示版本号。即&lt;PackageReference Include="Newtonsoft.Json"&gt; 有什么我想念的吗? @sellotape
    • @Avihay - 它只是在那里显示 .csproj 中的行。查看您的 .csproj 内部,看看是否与我的示例中的内容有根本不同。
    • 诚然是一个不错的尝试,但任何阅读本文的人都必须记住,这可能无法准确地表示包引用,因为 MSBuild 或 dotnet cli 会解决它们。暗示条件版本引用的更复杂的场景可能会导致问题。在Directory.Build.props 文件中,可能还存在对为所有项目设置一次的包的引用。当然,这不太可能。但它可能发生在一些拥有私人包的商店,这些包仅仅是用于 MSBuild 帮助的工具和/或只包含私人资产。
    • 只是一个想法:也许提取dotnet list package 的输出可能“更安全”?
    【解决方案4】:

    由于软件包依赖项已移至 package.config 文件中,因此这里是 https://stackoverflow.com/users/2385218/sellotape 提供的 Powershell 的更新版本

    Get-Content .\NP.sln | where { $_ -match "Project.+, ""(.+)\\([^\\]+).csproj"", " } | foreach { "$($matches[1])\packages.config" } | % { Get-Content $_ | Find "<package id" } | Sort-Object -Unique
    

    输出会是这样的:

    <package id="AutoMapper" version="8.1.1" targetFramework="net47" />
    <package id="BouncyCastle" version="1.8.5" targetFramework="net47" />
    <package id="CsvHelper" version="12.1.2" targetFramework="net47" />
    <package id="DnsClient" version="1.2.0" targetFramework="net47" />
    <package id="EntityFramework" version="6.2.0" targetFramework="net462" />
    <package id="EntityFramework" version="6.2.0" targetFramework="net47" />
    

    【讨论】:

      【解决方案5】:

      对于可以使用 PowerShell 的 .NET Core 2.2 及更高版本的项目,请尝试

      (dotnet list package) -match '^.*>' -replace '^ +> ','' | % { $_.split(" ")[0] } | Sort-Object -Unique
      

      dotnet list package | grep '>' | sed 's/^ *> //g;s/ \+/ /g' | cut -f 1 -d ' ' | sort -u
      

      在类似 POSIX 的环境中。

      【讨论】:

      • 我们如何获得版本?
      【解决方案6】:

      按照 selotape 的建议,编写一个脚本来查找每个 csproj 文件中出现的标记 PackageReference 是一个好主意。

      如果您的 csproj 文件包含以下内容,则此解决方案将不起作用:

      <PackageReference Include"SomePackage">
          <Version>1.0.42</Version>
      </PackageReference>
      

      尽管我建议您更改格式以内联声明版本(如 .NET Standard csproj 格式),但您可能没有时间为所有项目都这样做。

      解决办法:

      使用 C# 脚本,您可以获取 csproj 文件中包含 PackageReference 作为其标记名的所有项目。 然后你可以做以下两件事之一:

      1. 继续删除文本,直到找到(对于每个项目)这样的正则表达式: (Version="*"),这将允许您找到每个 PackageReference 的版本
      2. 将项目序列化为您喜欢的格式(JSON 工作),以将数据划分到字典中,您可以从中获取名称和版本,以及您可能需要的任何其他数据。

      我希望这会有所帮助。

      【讨论】:

        【解决方案7】:

        我为此编写了一个 C# 脚本,但它不直接使用 SLN 文件。相反,它会在给定目录中搜​​索任何 packages.config 文件。 重复项将在“程序集”列(使用指定包的所有程序集的列表)中可见。 输出将是任何给定位置的 CSV 文件。

        您可以从这里复制/下载或调整代码: Source Code

        您还可以使用 CMD / Powershell 编译上述编写的源代码: Compiling/Executing a C# Source File in Command Prompt

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-07
          • 2016-04-18
          • 2022-10-14
          • 1970-01-01
          • 2018-01-07
          • 1970-01-01
          相关资源
          最近更新 更多