functions/Get-HelpContent.ps1
function Get-HelpContent { <# .SYNOPSIS Liest die Comment-Based Help einer Funktion aus einer `.ps1`-Datei aus und gibt die Informationen strukturiert zurück. .DESCRIPTION Die Funktion `Get-HelpContent` analysiert eine angegebene PowerShell-Datei (`.ps1`) und extrahiert den Comment-Based Help-Block einer bestimmten Funktion. Dabei werden sowohl Blockkommentare als auch Zeilenkommentare vor oder nach der Funktionsdefinition berücksichtigt. Rückgegeben wird ein Objekt mit den Feldern SYNOPSIS, DESCRIPTION, PARAMETER (als Hashtable), EXAMPLE, NOTES und LINK. .PARAMETER FilePath Pfad zur Quelldatei (`.ps1`), die die Ziel-Funktion enthält. .PARAMETER FunctionName Name der Funktion, deren Hilfeinformationen extrahiert werden sollen. .EXAMPLE Get-HelpContent -FilePath '.\MyFunctions.ps1' -FunctionName 'Get-Weather' Liest die Hilfeinformationen der Funktion `Get-Weather` aus der Datei `MyFunctions.ps1` aus und gibt ein strukturiertes Objekt zurück. .OUTPUTS [pscustomobject] Ein Objekt mit folgenden Eigenschaften: - SYNOPSIS [string] - DESCRIPTION [string] - PARAMETER [hashtable] - EXAMPLE [string] - NOTES [string] - LINK [string] .NOTES Diese Funktion ist besonders nützlich für Skripte, die automatische Dokumentation erstellen oder die Qualität von Kommentaren analysieren. Bei fehlender Hilfe werden leere Felder zurückgegeben. #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$FilePath, [Parameter(Mandatory)][string]$FunctionName ) function Find-LineIndex { param ( [string[]]$Lines, [string]$Pattern ) for ($i = 0; $i -lt $Lines.Count; $i++) { if ($Lines[$i] -match $Pattern) { return $i } } return -1 } function Find-LineCommentsBlock { param( [string[]]$Lines, [int]$StartIndex, [int]$Direction ) $commentLines = @() $i = $StartIndex while ($i -ge 0 -and $i -lt $Lines.Count) { $line = $Lines[$i].Trim() if ($line -like '#*') { $commentLines += $line.TrimStart('#').TrimEnd() $i += $Direction } elseif ($commentLines.Count -gt 0) { break } else { $i += $Direction } } if ($Direction -eq -1) { [array]::Reverse($commentLines) } return $commentLines } $lines = Get-Content -Path $FilePath $funcLineIndex = Find-LineIndex -Lines $lines -Pattern "function\s+$FunctionName\b" if ($funcLineIndex -lt 0) { Write-Warning "Funktion '$FunctionName' nicht gefunden." return $null } # Suche Block-Kommentar vor Funktion (max 10 Zeilen) $helpBlock = $null for ($offset = 1; $offset -le 10; $offset++) { $tryIndex = $funcLineIndex - $offset if ($tryIndex -lt 0) { break } if ($lines[$tryIndex].Trim() -like '<#*') { for ($endIndex = $tryIndex; $endIndex -lt $lines.Count; $endIndex++) { if ($lines[$endIndex].Trim() -like '*#>') { $helpBlock = $lines[$tryIndex..$endIndex] break } } if ($helpBlock) { break } } } # Falls kein Block-Kommentar, versuche mehrzeilige # Kommentare vor Funktion if (-not $helpBlock) { $helpBlock = Find-LineCommentsBlock -Lines $lines -StartIndex ($funcLineIndex - 1) -Direction -1 if ($helpBlock.Count -eq 0) { $helpBlock = $null } } # Falls vor Funktion nichts, suche Block-Kommentar nach Funktion if (-not $helpBlock) { for ($offset = 1; $offset -le 10; $offset++) { $tryIndex = $funcLineIndex + $offset if ($tryIndex -ge $lines.Count) { break } if ($lines[$tryIndex].Trim() -like '<#*') { for ($endIndex = $tryIndex; $endIndex -lt $lines.Count; $endIndex++) { if ($lines[$endIndex].Trim() -like '*#>') { $helpBlock = $lines[$tryIndex..$endIndex] break } } if ($helpBlock) { break } } } if (-not $helpBlock) { $helpBlock = Find-LineCommentsBlock -Lines $lines -StartIndex ($funcLineIndex + 1) -Direction 1 if ($helpBlock.Count -eq 0) { $helpBlock = $null } } } if (-not $helpBlock) { Write-Verbose "Keine Comment-Based Help für Funktion '$FunctionName' gefunden." return [pscustomobject]@{ SYNOPSIS = '' DESCRIPTION = '' PARAMETER = @{} EXAMPLE = '' NOTES = '' LINK = '' } } # Entferne führende <# und abschließende #> falls vorhanden if ($helpBlock[0] -match '^\s*<#') { $helpBlock[0] = $helpBlock[0] -replace '^\s*<#', '' } $lastIndex = $helpBlock.Count - 1 if ($helpBlock[$lastIndex] -match '#>\s*$') { $helpBlock[$lastIndex] = $helpBlock[$lastIndex] -replace '#>\s*$', '' } $helpLines = $helpBlock | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' } $result = @{ SYNOPSIS = '' DESCRIPTION = '' PARAMETER = @{} EXAMPLE = @() NOTES = '' LINK = '' } $currentTag = '' $currentParam = '' $buffer = @() function Save-Buffer { param ( [string]$Tag, [string]$ParamName, [string[]]$Buffer ) $text = ($Buffer -join "`n").Trim() switch ($Tag.ToUpper()) { 'SYNOPSIS' { $result.SYNOPSIS = $text } 'DESCRIPTION' { $result.DESCRIPTION = $text } 'PARAMETER' { if ($ParamName) { if ($result.PARAMETER.ContainsKey($ParamName)) { $result.PARAMETER[$ParamName] += "`n" + $text } else { $result.PARAMETER[$ParamName] = $text } } } 'EXAMPLE' { $result.EXAMPLE += $text } 'NOTES' { $result.NOTES = $text } 'LINK' { $result.LINK = $text } } } foreach ($line in $helpLines) { if ($line -match '^\.(SYNOPSIS|DESCRIPTION|PARAMETER|EXAMPLE|NOTES|LINK)\s*(.*)') { # Speichere vorherigen Buffer if ($buffer.Count -gt 0) { Save-Buffer -Tag $currentTag -ParamName $currentParam -Buffer $buffer $buffer = @() } $currentTag = $matches[1].ToUpper() $paramText = $matches[2].Trim() if ($currentTag -eq 'PARAMETER') { # Vorherigen Parameter speichern falls offen if ($currentParam -ne '') { Save-Buffer -Tag 'PARAMETER' -ParamName $currentParam -Buffer $buffer $buffer = @() } # Neuer Parametername $currentParam = $paramText.Split()[0] # Beschreibung evtl. auf derselben Zeile? $desc = $paramText.Substring($currentParam.Length).Trim() if ($desc) { $buffer += $desc } } else { $currentParam = '' if ($paramText) { $buffer += $paramText } } } elseif ($line -match '^\.\S+') { # Anderes unbekanntes Tag -> vorherigen Buffer speichern if ($buffer.Count -gt 0) { Save-Buffer -Tag $currentTag -ParamName $currentParam -Buffer $buffer $buffer = @() } $currentTag = '' $currentParam = '' } else { if ($currentTag) { $buffer += $line } } } # letzten Buffer speichern if ($buffer.Count -gt 0) { Save-Buffer -Tag $currentTag -ParamName $currentParam -Buffer $buffer } # EXAMPLE als Mehrzeiler zusammenführen mit doppeltem Zeilenumbruch $result.EXAMPLE = ($result.EXAMPLE -join "`n`n").Trim() return [pscustomobject]$result } |