如何以编程方式列出解决方案中的所有项目?

Posted

技术标签:

【中文标题】如何以编程方式列出解决方案中的所有项目?【英文标题】:How do I programmatically list all projects in a solution? 【发布时间】:2011-04-17 15:39:06 【问题描述】:

我将接受脚本、命令行或 API 调用。

【问题讨论】:

【参考方案1】:

只需从 *.sln 文件中读取列表。有“项目”-“结束项目”部分。 这里是an article from MSDN.

【讨论】:

@Kiquenet 恐怕我没听懂你的评论 没有任何 Parser C# class 用于读取 sln 文件 吗?类似 ***.com/questions/707107/… ***.com/questions/1243022/…【参考方案2】:

如果您将程序编写为 Visual Studio 插件,您可以访问 EnvDTE 以查找当前打开的解决方案中的所有项目。

【讨论】:

【参考方案3】:

这是一个从 .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]
      
    

【讨论】:

我知道这是旧的,但它很漂亮。为我节省了很多时间。 如果需要,您可以通过在第 2 行和第 3 行之间添加额外的 Select-String 来过滤解决方案文件夹,如下所示:Select-String "2150E333-8FDC-42A3-9474-1A3956D46DE8" -NotMatch |【参考方案4】:

您可以使用 EnvDTE.Solution.Projects 对象以编程方式访问解决方案中的项目。

一个问题是,如果您的解决方案中有任何解决方案文件夹,则这些文件夹中的任何项目都不会显示在上述集合中。

我写了一篇文章,其中包含一个代码示例,说明 to get all projects 不考虑任何解决方案文件夹

【讨论】:

这只能在 VS 扩展中使用,因此对于任何想要一个独立工具来读取解决方案中的源项目的人来说都是无用的。 您可以获得对running instance of VS 的引用,或者您可以从包管理器控制台访问$dte。如果您根本没有运行 VS,那么您需要一个替代解决方案。新的 MSBuild 包现在包含用于解析解决方案和项目文件的类,但这些仍然是 RTM 之前的 更新链接:wwwlicious.com/envdte-getting-all-projects-html【参考方案5】:
    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 的评论修改正则表达式以包含“.*”

【讨论】:

上述方法可行,但有一个小问题。如果您的项目命名为“AB.CD” - 我的意思是当“。”在那里,那么正则表达式将无法识别那些。下面的小改动可以使它起作用 - Regex projReg = new Regex("Project\(\"\\[\\w-]*\\\"\) = \"([\\w _]*. *)\", \"(.*\\.(cs|vcx|vb)proj)\"" , RegexOptions.Compiled); 像魅力一样工作!【参考方案6】:

这里有一个非常优雅的解决方案:Parsing Visual Studio Solution files

John Leidegren 的回答涉及包装内部 Microsoft.Build.Construction.SolutionParser 类。

【讨论】:

【参考方案7】:

目前您可以在 VS 中使用Package Manager Console 来获取该信息。使用 powershell Get-Project 命令

Get-Project -All

【讨论】:

哪个 Visual Studio version ?【参考方案8】:

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

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

【讨论】:

【参考方案9】:

自 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、配置等)。在上面的示例中,我使用 ProjectType 过滤掉解决方案文件夹。

【讨论】:

对于VS2017来说,是在VS2017下"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\amd64\Microsoft.Build.dll" 和烦人,但是对于sqlprojs文件,项目类型是Unknown [SolutionProjectType]::Unknown【参考方案10】:

诀窍是选择正确的 MsBuild.dll。 在 VS2017 下确实是“C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\amd64\Microsoft.Build.dll” (不要在引用中使用标准的 Msbuild ddl。浏览到此路径)

c#:

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;
     
  

powershell:

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
    
  

【讨论】:

【参考方案11】:

我知道这可能是已经回答的问题,但我想分享我阅读 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" 

希望这会有所帮助。

【讨论】:

【参考方案12】:

通过@brianpeiris扩展answer:

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 获取每个完整的文件路径。

我想要完整路径的原因是能够访问每个项目文件旁边的packages.config 文件,然后从所有这些文件中获取包:

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

【讨论】:

以上是关于如何以编程方式列出解决方案中的所有项目?的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式递归列出eclipse工作区中的所有文件

以编程方式:列出在实体框架模型中找到的所有存储过程

如何以编程方式选择 WPF TreeView 中的项目?

如何以编程方式列出 C++ 或 Python 中的 DLL 依赖项?

列出 ASP.MVC 中的所有视图

列出Matlab中的所有环境变量