【发布时间】:2011-04-17 15:39:06
【问题描述】:
如何以编程方式列出解决方案中的所有项目?我将接受脚本、命令行或 API 调用。
【问题讨论】:
标签: c# visual-studio-2008 scripting projects-and-solutions
如何以编程方式列出解决方案中的所有项目?我将接受脚本、命令行或 API 调用。
【问题讨论】:
标签: c# visual-studio-2008 scripting projects-and-solutions
只需从 *.sln 文件中读取列表。有“项目”-“结束项目”部分。
这里是an article from MSDN.
【讨论】:
如果您将程序编写为 Visual Studio 插件,您可以访问 EnvDTE 以查找当前打开的解决方案中的所有项目。
【讨论】:
这是一个从 .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]
}
}
【讨论】:
Select-String "{2150E333-8FDC-42A3-9474-1A3956D46DE8}" -NotMatch |
您可以使用 EnvDTE.Solution.Projects 对象以编程方式访问解决方案中的项目。
一个问题是,如果您的解决方案中有任何解决方案文件夹,则这些文件夹中的任何项目都不会显示在上述集合中。
我写了一篇文章,其中包含一个代码示例,说明 to get all projects 不考虑任何解决方案文件夹
【讨论】:
$dte。如果您根本没有运行 VS,那么您需要一个替代解决方案。新的 MSBuild 包现在包含用于解析解决方案和项目文件的类,但这些仍然是 RTM 之前的
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 的评论修改正则表达式以包含“.*”
【讨论】:
这里有一个非常优雅的解决方案:Parsing Visual Studio Solution files
John Leidegren 的回答涉及包装内部 Microsoft.Build.Construction.SolutionParser 类。
【讨论】:
目前您可以在 VS 中使用Package Manager Console 来获取该信息。使用 powershell Get-Project 命令
Get-Project -All
【讨论】:
version ?
如果您需要在非 Windows 机器上执行此操作,可以使用以下 Bash 命令:
grep "Project(" NameOfYourSolution.sln | cut -d'"' -f4
【讨论】:
自 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 过滤掉解决方案文件夹。
【讨论】:
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\amd64\Microsoft.Build.dll" 和烦人,但是对于sqlprojs文件,项目类型是Unknown [SolutionProjectType]::Unknown
诀窍是选择正确的 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}
}
}
【讨论】:
我知道这可能是已经回答的问题,但我想分享我阅读 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"
}
希望这会有所帮助。
【讨论】:
通过@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
【讨论】: