ps/Modules/Cole.PowerShell.Developer/Public/ConvertFrom-SlnFile.ps1

135 lines
6.0 KiB
PowerShell
Raw Normal View History

2023-05-30 22:51:22 -07:00
function ConvertFrom-SlnFile {
<#
.SYNOPSIS
Reads in a solution file and returns a useful output object
#>
[CmdletBinding()]
[OutputType([object])]
param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
$Path
)
$logLead = (Get-LogLeadName)
if (!(Test-Path -Path $Path)) {
Write-Warning "$logLead : Can not find the file specified at [$Path]. Please verify it exists and is accessible."
return
}
if (!$Path.EndsWith('.sln')) {
if ((Get-Item -Path $Path).PSIsContainer) {
$paths = (Get-ChildItem -Path (Join-Path $Path "*.sln" -Recurse))
$pathsCount = $paths.Count
if ($pathsCount -gt 0) {
$Path = $paths[0]
if ($pathsCount -eq 1) {
Write-Host "$logLead : Found the following file under the specified folder. Using this file [$Path]."
} else {
Write-Host "$logLead : Found $($pathsCount) paths in subfolder. Will process only the first record at [$Path]."
}
} else {
Write-Warning "$logLead : Found no sln folders in file. Can not do anything. Returning null."
return $null
}
} else {
Write-Warning "$logLead : Path [$Path] does not end with [.sln] and is not a folder, may not parse properly"
}
}
$solutionPath = (Split-Path -Path $Path -Parent)
$lines = (Get-Content -Path $Path)
if ($lines.Count -eq 0) {
Write-Error "$logLead : No contents found in [$Path]. Can not continue."
return $null
}
$solutionFile = @{ Projects = @(); }
$parsingProject = $false
$parsingProjectSection = $false
$parsingGlobal = $false
$currentProject = @{ Name = ''; Type = ''; Path = ''; Guid = ''; }
foreach ($line in $lines) {
$line = $line.Trim()
if ($line.StartsWith('#') -or [string]::IsNullOrWhiteSpace($line)) {
# Skip the comment and blank lines, we don't care
} elseif ($line.StartsWith("Project(")) {
# Parse project line
$parsingProject = $true
# example line
# Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Alkami.Admin.FicoScore", "Alkami.Admin.FicoScore\Alkami.Admin.FicoScore.csproj", "{E1475E57-C4FB-401E-9404-1B48BD473C5C}"
# Project(clsid) = projectName, projectPath (from solution root), projectGuid
$splits = $line -split ','
if ($splits.Count -ne 3) {
Write-Warning "$logLead : An unexpected (found: $($splits.Count), expected: 3) number of segments were found for this line [$line]. Expected format: [Project(clsid) = projectName, projectPath, projectGuid]. Will attempt to process."
}
$projectClsidAndName = $splits[0].Trim().Replace('"','').Replace('{','').Replace('}','')
$projectRelativePath = $splits[1].Trim().Replace('"','')
$projectGuid = $splits[2].Trim().Replace('"','').Replace('{','').Replace('}','')
$projectClsidAndNameSplits = $projectClsidAndName -split('=')
$projectClsid = $projectClsidAndNameSplits[0].Trim().Replace('Project(','').Replace(')','')
$projectName = $projectClsidAndNameSplits[1].Trim()
$projectType = (Get-DotNetProjectFileTypeFromGuid -ProjectTypeGuid $projectClsid)
if ($projectType -eq 'Solution Folder') {
# there is no path here
} else {
# there is a path here
$fullProjectPath = (Join-Path -Path $solutionPath -ChildPath $projectRelativePath)
$currentProject.Path = $fullProjectPath
}
$currentProject.Name = $projectName
$currentProject.Guid = $projectGuid
$currentProject.Type = $projectType
} elseif ($line.StartsWith("EndProject")) {
# End parsing a project
if (![string]::IsNullOrWhiteSpace($currentProject.Name)) {
$solutionFile.Projects += $currentProject
}
$parsingProject = $false
$currentProject = @{ Name = ''; Type = ''; Path = ''; Guid = ''; }
} elseif ($line -eq "Global") {
# Start parsing global configuration data
$parsingGlobal = $true
} elseif ($line -eq "EndGlobal") {
# End parsing global configuration data
$parsingGlobal = $false
} elseif ($line.StartsWith("VisualStudioVersion")) {
# Parse global configuration data
$solutionFile.VisualStudioVersion = $line.Split('=')[0].Trim()
} elseif ($line.StartsWith("MinimumVisualStudioVersion")) {
# Parse global configuration data
$solutionFile.MinimumVisualStudioVersion = $line.Split('=')[0].Trim()
} elseif ($line.StartsWith("Microsoft Visual Studio Solution File")) {
# Parse global configuration data
$solutionFile.SolutionFileVersion = $line.Split(',')[1].Trim()
} elseif ($parsingProject) {
# Parse project information
if ($line.StartsWith('ProjectSection')) {
$parsingProjectSection = $true
$currentProject.ProjectFiles = @()
} elseif ($line.StartsWith('EndProjectSection')) {
$parsingProjectSection = $false
} elseif ($parsingProjectSection) {
$splits = $line -split '='
$currentProject.ProjectFiles += @{ Name = $splits[0].Trim(); Value = $splits[1].Trim(); }
} else {
Write-Host "$logLead : Not sure how to parse this projectSection line`r`n`t$line"
}
} elseif ($parsingGlobal) {
# Parse global configuration data
# TODO: I don't need this information right now
# Still here in case I decide one day I want to capture it
} else {
Write-Host "$logLead : Not sure how to parse this line`r`n`t$line"
}
}
return $solutionFile
}