簡體   English   中英

如何以編程方式列出解決方案中的所有項目?

[英]How do I programmatically list all projects in a solution?

如何以編程方式列出解決方案中的所有項目? 我將接受腳本、命令行或 API 調用。

這是一個從 .sln 文件中檢索項目詳細信息的 PowerShell 腳本:

Get-Content 'Foo.sln' |
  Select-String 'Project\(' |
    ForEach-Object {
      $projectParts = $_ -Split '[,=]' | ForEach-Object { $_.Trim('[ "{}]') };
      New-Object PSObject -Property @{
        Name = $projectParts[1];
        File = $projectParts[2];
        Guid = $projectParts[3]
      }
    }
    var Content = File.ReadAllText(SlnPath);
    Regex projReg = new Regex(
        "Project\\(\"\\{[\\w-]*\\}\"\\) = \"([\\w _]*.*)\", \"(.*\\.(cs|vcx|vb)proj)\""
        , RegexOptions.Compiled);
    var matches = projReg.Matches(Content).Cast<Match>();
    var Projects = matches.Select(x => x.Groups[2].Value).ToList();
    for (int i = 0; i < Projects.Count; ++i)
    {
        if (!Path.IsPathRooted(Projects[i]))
            Projects[i] = Path.Combine(Path.GetDirectoryName(SlnPath),
                Projects[i]);
        Projects[i] = Path.GetFullPath(Projects[i]);
    }

編輯:根據 Kumar Vaibhav 的評論修改正則表達式以包含“.*”

您可以使用 EnvDTE.Solution.Projects 對象以編程方式訪問解決方案中的項目。

但有一個問題是,如果您的解決方案中有任何 SolutionFolders,則這些文件夾中的任何項目都不會顯示在上述集合中。

我寫了一篇文章,其中包含一個關於如何獲取所有項目而不考慮任何解決方案文件夾的代碼示例

目前,您可以在 VS 中使用包管理器控制台來獲取該信息。 使用 powershell Get-Project命令

Get-Project -All

訣竅是選擇正確的 MsBuild.dll。 在 VS2017 下,它確實是“C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\MSBuild\\15.0\\Bin\\amd64\\Microsoft.Build.dll”(不要在引用中使用標准的 Msbuild ddl。瀏覽到這個路徑)

代碼:

var solutionFile =    
SolutionFile.Parse(@"c:\NuGetApp1\NuGetApp1.sln");//your solution full path name
var projectsInSolution = solutionFile.ProjectsInOrder;
foreach(var project in projectsInSolution)
{
   switch (project.ProjectType)
   {
      case SolutionProjectType.KnownToBeMSBuildFormat:
     {
         break;
     }
     case SolutionProjectType.SolutionFolder:
     {
         break;
     }
  }
}

電源外殼:

Add-Type -Path (${env:ProgramFiles(x86)} + '\Microsoft Visual 
Studio\2017\Professional\MSBuild\15.0\Bin\amd64\Microsoft.Build.dll')

$slnPath = 'c:\NuGetApp1\NuGetApp1.sln'
$slnFile = [Microsoft.Build.Construction.SolutionFile]::Parse($slnPath)
$pjcts = $slnFile.ProjectsInOrder

foreach ($item in $pjcts)
{

    switch($item.ProjectType)
    {
        'KnownToBeMSBuildFormat'{Write-Host Project  : $item.ProjectName}
        'SolutionFolder'{Write-Host Solution Folder : $item.ProjectName}
    }
}  

只需從 *.sln 文件中讀取列表。 有“項目”-“結束項目”部分。
這是MSDN的一篇文章。

從 powershelll 和解決方案的文件夾中寫入

do.net sln 列表

這里有一個非常優雅的解決方案: 解析 Visual Studio 解決方案文件

John Leidegren 的回答涉及包裝內部Microsoft.Build.Construction.SolutionParser類。

如果您將程序編寫為 Visual Studio EnvDTE ,您可以訪問EnvDTE以找出當前打開的解決方案中的所有項目。

從 Visual Studio 2013 開始,Microsoft.Build.dll 提供了一個帶有一些非常方便的函數的 SolutionFile 對象。

下面是一個使用 v14.0 版本的示例,按照它們在解決方案中出現的順序列出所有項目的相對路徑。

Add-Type -Path (${env:ProgramFiles(x86)} + '\Reference Assemblies\Microsoft\MSBuild\v14.0\Microsoft.Build.dll')
$solutionFile = '<FULL PATH TO SOLUTION FILE>'
$solution = [Microsoft.Build.Construction.SolutionFile] $solutionFile
($solution.ProjectsInOrder | Where-Object {$_.ProjectType -eq 'KnownToBeMSBuildFormat'}).RelativePath

項目對象上還有許多其他可能有用的屬性(ProjectName、AbsolutePath、configuration 等)。 在上面的示例中,我使用 ProjectType 過濾掉解決方案文件夾。

我知道這可能已經回答了問題,但我想分享我閱讀 sln 文件的方法。 同樣在運行時我正在確定項目是否是測試項目

function ReadSolutionFile($solutionName)
{
    $startTime = (Get-Date).Millisecond
    Write-Host "---------------Read Start---------------" 
    $solutionProjects = @()

    dotnet  sln "$solutionName.sln" list | ForEach-Object{     
        if($_  -Match ".csproj" )
        {
            #$projData = ($projectString -split '\\')

            $proj = New-Object PSObject -Property @{

                Project = [string]$_;
                IsTestProject =   If ([string]$_ -Match "test") {$True} Else {$False}  
            }

            $solutionProjects += $proj

        }
    }

    Write-Host "---------------Read finish---------------" 
    $solutionProjects

    $finishTime = (Get-Date).Millisecond
    Write-Host "Script run time: $($finishTime-$startTime) mil" 
}

希望這會有所幫助。

如果您需要在非 Windows 機器上執行此操作,可以使用以下 Bash 命令:

grep "Project(" NameOfYourSolution.sln | cut -d'"' -f4

要擴展@brianpeiris答案

Function Global:Get-ProjectInSolution {
    [CmdletBinding()] param (
        [Parameter()][string]$Solution
    )
    $SolutionPath = Join-Path (Get-Location) $Solution
    $SolutionFile = Get-Item $SolutionPath
    $SolutionFolder = $SolutionFile.Directory.FullName

    Get-Content $Solution |
        Select-String 'Project\(' |
        ForEach-Object {
            $projectParts = $_ -Split '[,=]' | ForEach-Object { $_.Trim('[ "{}]') }
            [PSCustomObject]@{
                File = $projectParts[2]
                Guid = $projectParts[3]
                Name = $projectParts[1]
            }
        } |
        Where-Object File -match "csproj$" |
        ForEach-Object {
            Add-Member -InputObject $_ -NotePropertyName FullName -NotePropertyValue (Join-Path $SolutionFolder $_.File) -PassThru
        }
}

這僅過濾到.csproj文件,並根據File字段和包含sln文件的路徑添加每個文件的完整路徑。

使用Get-ProjectInSolution MySolution.sln | Select-Object FullName Get-ProjectInSolution MySolution.sln | Select-Object FullName以獲取每個完整文件路徑。

我想要完整路徑的原因是能夠訪問每個項目文件旁邊的packages.config文件,然后從所有這些文件中獲取包:

Get-ProjectInSolution MySolution.sln |
    %{Join-Path ($_.FullName | Split-Path) packages.config} |
    %{select-xml "//package[@id]" $_ | %{$_.Node.GetAttribute("id")}} |
    select -unique

這是我用來從解決方案第一的立場來看問題的一種修改方法:

Function Get-ProjectReferences ($rootFolder) {
    $ns = @{ defaultNamespace = "http://schemas.microsoft.com/developer/msbuild/2003" }
    $solutionFilesWithContent = Get-ChildItem $rootFolder -Filter *.sln -Recurse |
    ForEach-Object {
        New-Object PSObject -Property @{
            SolutionFile    = $_;
            SolutionContent = Get-Content $_;
        }
    }
    $projectFilesWithContent = Get-ChildItem $rootFolder -Filter *.csproj -Recurse |
    ForEach-Object {
        New-Object PSObject -Property @{
            ProjectFile    = $_;
            ProjectContent = [xml](Get-Content $_);
        }  
    }

    $solutionFilesWithContent | ForEach-Object {
        $solutionFileWithContent = $_
        $projectsInSolutionStrings = $solutionFileWithContent.SolutionContent | Select-String 'Project\('
        $projectsInSolution = $projectsInSolutionStrings |
        ForEach-Object {
            $projectParts = $_ -Split '[,=]' | ForEach-Object { $_.Trim('[ "{}]') };
            if ($projectParts[2].Contains(".csproj")) {
                New-Object PSObject -Property @{
                    Name = $projectParts[1];
                    File = $projectParts[2];
                    Guid = $projectParts[3];
                }                    
            }
        }

        $projectsInSolution | ForEach-Object {
            $projectFileSearchName = $_.Name + ".csproj"
            $projectInSolutionFile = $projectFilesWithContent | Where-Object { $_.ProjectFile.Name -eq $projectFileSearchName } | Select-Object -First 1
            if (($null -eq $projectInSolutionFile) -and ($null -eq $projectInSolutionFile.ProjectContent)) {
                Write-Host "Project was null"
            }
            else {
                $projectInSolutionName = $projectInSolutionFile.ProjectFile | Select-Object -ExpandProperty BaseName
                $projectReferences = $projectInSolutionFile.ProjectContent | Select-Xml '//defaultNamespace:ProjectReference/defaultNamespace:Name' -Namespace $ns | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty "#text"
                $projectTarget = $projectInSolutionFile.ProjectContent | Select-Xml "//defaultNamespace:TargetFrameworkVersion" -Namespace $ns | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty "#text"
        
                $projectReferences | ForEach-Object {
                    $projectFileName = $_ + ".csproj"
                    $referenceProjectFile = $projectFilesWithContent | Where-Object { $_.ProjectFile.Name -eq $projectFileName } | Select-Object -First 1
                    if ($null -eq $referenceProjectFile) {
                        $referenceProjectTarget = "Unknown"
                    }
                    else {
                        $referenceProjectTarget = $referenceProjectFile.ProjectContent | Select-Xml "//defaultNamespace:TargetFrameworkVersion" -Namespace $ns | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty "#text"                    
                    }
                    "[" + $solutionFileWithContent.SolutionFile.Name + "] -> [" + $projectInSolutionName + " " + $projectTarget + "] -> [" + $_ + " " + $referenceProjectTarget + "]"
                }
            }
        }
    }
}

Get-ProjectReferences "C:\src\repos\MyRepo" | Out-File "C:\src\repos\FrameworkDependencyAnalysis\FrameworkDependencyAnalysis.txt"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM