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

时间:2010-09-27 08:07:44

标签: c# visual-studio-2008 scripting projects-and-solutions

如何以编程方式列出解决方案中的所有项目?我将接受脚本,命令行或API调用。

12 个答案:

答案 0 :(得分:46)

这是一个PowerShell脚本,用于从.sln文件中检索项目详细信息:

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

答案 1 :(得分:16)

    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的评论修改正则表达式包含“。*”

答案 2 :(得分:10)

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

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

我写过一篇文章,其中包含to get all projects如何与任何解决方案文件夹无关的代码示例

答案 3 :(得分:6)

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

Get-Project -All

答案 4 :(得分:4)

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

答案 5 :(得分:3)

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

答案 6 :(得分:3)

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

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

答案 7 :(得分:3)

诀窍是选择正确的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}
    }
}  

答案 8 :(得分:1)

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

// print out data in the desired format foreach($openSeats as $year=>$months){ foreach($months as $month=>$openSeatsThisMonth){ echo "$month/$year - $openSeatsThisMonth<br>"; } }

答案 9 :(得分:1)

自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过滤掉了解决方案文件夹。

答案 10 :(得分:0)

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

希望这会有所帮助。

答案 11 :(得分:0)

要在answer上用@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获取每个完整的文件路径。

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

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