Getting Version Data From Comment Based Help

Disclaimer: There’s a lot of parse-by-prayer here.  You Have Been Warned.

Here’s the short form: I try to keep a change log of sorts in the comment-based help for my scripts.  (I say try because that’s sadly the first thing to be omitted when I’m in a hurry.  Code clarity is sadly second.)  It looks something like this:

 <#
.NOTES
Who         What        When        Why
timdunn     v1.0        2014-01-25  What’s the point?
#>

Yes, indeed. Why do we bother?

Well, it turns out you can get the data from the ‘NOTES’ section, though not in a way that makes any sense to me.

 (Get-Help $Path).AlertSet.Alert

That returns the ‘NOTES’ data.  I’m not sure it does me a lot of good, though.  Digging into it, the actual data is stored as a single string under:

 (Get-Help $Path).AlertSet.Alert.GetValue(0).Text

This is, as mentioned before, a single string.  From here, we do some slice-n-dicing with Split(), –replace, and the usual other set of tools at our disposal.

function Get-VersionDataFromHelp
{
     <#

    .SYNOPSIS
Get version data from NOTES section of Comment-Based-Help

.DESCRIPTION
(Get-Help $Path).AlertSet returns the data from the '.NOTES' subheading.
The first line of this data set is expected to contain the words 'who, what', 'When', and 'why'.

.PARAMETER Path
Script or function from which to extract data.

.EXAMPLE
Get-VersionDataFromHelp Get-VersionDataFromHelp

Return version data from this function.

.EXAMPLE
Get-VersionDataFromHelp path/to/script.ps1

Return version data from specified file.

.NOTES
who what when why
timdunn V1.0 2014-01-25 Initial version

#>

     param (
         [string]$Path = $MyInvocation.MyCommand.Name
     );

     # Get NOTES data from command-based-help
     ####################
     $alertData = (Get-Help $Path -ErrorAction SilentlyContinue).AlertSet.Alert;
     if (!$alertData)
     {
         Write-Warning "$($MyInvocation.MyCommand.Name) Cannot find 'NOTES' section in $Path Comment-Based-Help. Stopping.";
         return;

     } # if (!$alertData)

     [string[]]$noteData = $alertData.GetValue(0).Text.Split("`n");
     if ($noteData.Count -le 1)
     {
         Write-Warning "$($MyInvocation.MyCommand.Name) Cannot find 'NOTES' data in $Path Comment-Based-Help. Stopping.";
         return;

     } # if (!$noteData)

     # Extract Headers
     ####################
     $header = $noteData[0];
     @('Who', 'What', 'When', 'Why') | % {
         if ($header -notmatch $_){
             Write-Warning "$($MyInvocation.MyCommand.Name) First line of $Path Comment-Based-Help 'NOTES' data missing header '$_'. Stopping.";
        } # if ($header -notmatch $_){
     } # @('Who', 'What', 'When', 'Why') | % {

     [string[]]$headers = $header.Split(" ") | ? { $_; } | % { (Get-Culture).TextInfo.ToTitleCase($_.ToLower()); }

     if ($headers[($headers.Count - 1)] -notmatch 'Why')
     {
         Write-Warning "$($MyInvocation.MyCommand.Name) Invalid Schema: Last column of $Path Comment-Based-Help 'NOTES' data should be 'Why'. Stopping.";
     } # if ($headers[($headers.Count - 1)] -notmatch 'Why')
    
     # Process NOTES data
     ####################
     $noteData[1 .. ($noteData.Count - 1)] | % {
        
         $lineData = ($_ -replace "\s+", " ").Split(" ", $headers.Count);
         $object = New-Object -TypeName PsObject | Select-Object -Property $headers;
         Add-Member -InputObject $object -MemberType NoteProperty -Name Source -Value (Split-Path -Leaf $Path);
        
         foreach ($i in (0 .. ($headers.Count - 1)))
         {
             $object.($headers[$i]) = $lineData[$i];
             if (($headers[$i] -match 'When') -and !($lineData[$i] -as [DateTime]))
             { # if this line doesn't have 'When' data, stop processing.
                 return;

             } # if (($headers[$i] -match 'When') -and !($lineData[$i] -as [DateTime]))

         } # foreach ($i in (0 .. ($headers.Count - 1)))

         # return data
         $object; 

     } # $noteData[1 .. ($noteData.Count - 1)] | % {
    
} # function Get-VersionDataFromHelp