135 lines
6.0 KiB
PowerShell
135 lines
6.0 KiB
PowerShell
|
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
|
||
|
}
|