代码之家  ›  专栏  ›  技术社区  ›  joseville

PowerShell命令,用于从目录及其子目录中的所有.csproj文件中提取“<ProjectReference Include=(…)”

  •  1
  • joseville  · 技术社区  · 10 月前

    获取列表 .csproj 在目录和子目录中 D:\repos\M\Test

    1. PS D:\repos\M\Test> ls -r -filter "*.csproj" | select Directory, Name

    样本输出

    Directory                       Name
    ---------                       ----
    D:\repos\M\Test\M.Common        M.Common.csproj
    D:\repos\M\Test\M.Mocks         M.Mocks.csproj
    D:\repos\M\Test\M.StateMachines M.StateMachines.csproj
    

    获取包含匹配行的文件列表 <ProjectReference\s*Include="([^"]+)" 在目录和子目录中

    2. PS D:\repos\M\Test> ls | sls '<ProjectReference\s*Include="([^"]+)"' | ForEach-Object {New-Object PSObject -Property @{Project=$_.Filename; DirectDep=$_.Matches.Groups[1].Value}}

    样本输出

    Project                DirectDeps
    -------                ----------
    dirs.proj              D:\repos\M\Test\M.Common
    dirs.proj              D:\repos\M\Test\M.Mocks.csproj
    dirs.proj              D:\repos\M\Test\M.StateMachines.csproj
    M.Common.csproj        D:\repos\S\Common\Common.csproj
    M.Common.csproj        D:\repos\Q\Contracts\Contracts.csproj
    M.Mocks.csproj         D:\repos\S\Controller\Controller.csproj
    M.StateMachines.csproj D:\repos\M\Common\Common.csproj
    M.StateMachines.csproj D:\repos\T\Auth\Auth.csproj
    

    问题

    Q1:如何将[1]的输出馈送到[2],以将[2]的搜索限制为 .csproj 文件(即排除 dirs.proj )得到以下输出

    Project                DirectDeps
    -------                ----------
    M.Common.csproj        D:\repos\S\Common\Common.csproj
    M.Common.csproj        D:\repos\Q\Contracts\Contracts.csproj
    M.Mocks.csproj         D:\repos\S\Controller\Controller.csproj
    M.StateMachines.csproj D:\repos\M\Common\Common.csproj
    M.StateMachines.csproj D:\repos\T\Auth\Auth.csproj
    

    问题2:那么我如何获取[2]的输出,并按项目/文件名对其进行分组呢?获得以下输出(或类似输出)

    M.Common.csproj, D:\repos\S\Common\Common.csproj, D:\repos\Q\Contracts\Contracts.csproj
    M.Mocks.csproj, D:\repos\S\Controller\Controller.csproj
    M.StateMachines.csproj, D:\repos\M\Common\Common.csproj, D:\repos\T\Auth\Auth.csproj
    

    尝试

    Q1尝试次数

    • ls -r -filter "*.csproj" | ForEach-Object {"$_.Directory\$_.Name"}
    • ls -r -filter "*.csrpoj" | select Path
    • 答案: ls -r -filter "*.csproj" | [2]

    Q2尝试次数

    • ls | sls '<ProjectReference\s*Include="([^"]+)"' | ForEach-Object {New-Object PSObject -Property @{Project=$_.Filename; DirectDep=$_.Matches.Groups[1].Value}} | group Project
    • ls | sls '<ProjectReference\s*Include="([^"]+)"' | ForEach-Object {New-Object PSObject -Property @{Project=$_.Filename; DirectDep=$_.Matches.Groups[1].Value}} | group Project | select Name, Group
    • ls | sls '<ProjectReference\s*Include="([^"]+)"' | ForEach-Object {New-Object PSObject -Property @{Project=$_.Filename; DirectDep=$_.Matches.Groups[1].Value}} | group Project | select Name, Group.DirectDep

    3中的第二个输出最接近我要找的输出

    Name                   Group
    ----                   -----
    dirs.proj              {@{Project=dirs.proj; DirectDep=...M.Common.csproj}, {Project=dirs.proj; DirectDep=...M.Mocks.csproj}, {Project=dirs.proj; DirectDep=...M.StateMachines.csproj}
    M.Common.csproj        {@{Project=M.Common.csproj; DirectDep=...Common.csproj}, {Project=M.Common.csproj; DirectDep=...Contracts.csproj}}
    M.Mocks.csproj         {@{Project=M.Mocks.csproj; DirectDep=...Controller.csproj}
    M.StateMachines.csproj {@{Project=M.StateMachines.csproj; DirectDep=...Common.csproj}, {Project=M.StateMachines.csproj; DirectDep=...Auth.csproj}}
    
    1 回复  |  直到 10 月前
        1
  •  2
  •   Santiago Squarzon    10 月前

    所以,假设你确实有 .NET SDK 安装后,您可以简单地使用 dotnet list reference command 获取所有参考项目。

    代码类似于:

    Get-ChildItem -Recurse -Filter *.csproj | ForEach-Object {
        $references = dotnet list $_.FullName reference
        if ($references.Count -gt 2) {
            # When there are references found the first 2 lines will be:
    
            # Project reference(s)
            # --------------------
    
            # you can choose to skip them here if you want to or just remove this condition
            $references = $references | Select-Object -Skip 2
        }
    
        [pscustomobject]@{
            ProjectName       = $_.BaseName
            ProjectPath       = $_.FullName
            PackageReferences = $references
        }
    }
    

    至于前面的问题,“例如,如何排除, dirs.proj “,如果你使用 -Filter *.csproj 它根本不应该列出,但为了回答,你可以使用 -Exclude :

    Get-ChildItem -Recurse -Filter *.csproj -Exclude dirs.proj |
        ForEach-Object { .... } # same code shown above
    

    或者 Where-Object :

    Get-ChildItem -Recurse -Filter *.csproj |
        Where-Object Name -NE dirs.proj |
        ForEach-Object { .... } # same code shown above