Where Is the Standard Place to Put a Powershell Script Version Number?
Since Powershell Version 3 There Has Been Very Well Defined Comment Based Help Comment Block: What I Would Like to Know Is There a Standard for Versioning a...
Since PowerShell version 3 there has been very well defined comment based help comment block: What I would like to know is there a standard for versioning a PowerShell script like there is in C#? I am asking as I am about to publish a module and the psd1 file has:
# Version number of this module.
ModuleVersion = '1.0.0.0'
In my own scripts I use the following standard:
<#
.SYNOPSIS
<Synopsis goes here>.
.DESCRIPTION
<Description goes here>.
.EXAMPLE
Example.ps1
Runs with default parameters
.NOTES
Author : Glen Buktenica
Version : 1.0.0.0 20160725 Initial Build
#>
4 Answers
At the time of writing (and asking the question) - Afaik there's no "official" standard of doing this.
The most frequent used way I've seen people versioning their scripts are as you are doing under the .NOTES section
.NOTES
Version: 1.0
Author: <Name>
Creation Date: <Date>
Purpose/Change: Initial script development
I've also seen headers such as this on top of the script just after #requires statements. Ex: #script 1.0 - though less frequent
Since this is meta information and your script version will follow your module version, I'd say it should be a good solution to keep doing what you're already are doing (and what I've seen most people doing already).
Update: for newer versions of Powershell - look at the new-scriptfileinfo cmdlet:()
Use the ScriptFileInfo cmdlets, like: New-ScriptFileInfo
<#PSScriptInfo
.VERSION 1.0.1
.GUID 54688e75-298c-4d4b-a2d0-1234567890ab
.AUTHOR iRon
.DESCRIPTION Your description
.COMPANYNAME
.COPYRIGHT
.TAGS PowerShell Version
.LICENSEURI
.PROJECTURI
.ICONURI
.EXTERNALMODULEDEPENDENCIES
.REQUIREDSCRIPTS
.EXTERNALSCRIPTDEPENDENCIES
.RELEASENOTES
.PRIVATEDATA
#>
It is actually a pity that this is not standardized as it would open a way to get the information accessible from within you own code. e.g. If you want to log the version in a log file you do not want to redefine that version in another command in your cmdlet (simply because it might be forgotten and get out of sync with the header).
In my standard PowerShell LOg-Entry framework, I am using a few commands to make this assembly information easily available by default:
$My = @{File = Get-ChildItem $MyInvocation.MyCommand.Path; Contents = $MyInvocation.MyCommand.ScriptContents}
If ($My.Contents -Match '^\s*\<#([\s\S]*?)#\>') {$My.Help = $Matches[1].Trim()}
[RegEx]::Matches($My.Help, '(^|[\r\n])\s*\.(.+)\s*[\r\n]|$') | ForEach {
If ($Caption) {$My.$Caption = $My.Help.SubString($Start, $_.Index - $Start)}
$Caption = $_.Groups[2].ToString().Trim()
$Start = $_.Index + $_.Length
}
$My.Title = $My.Synopsis.Trim().Split("`r`n")[0].Trim()
$My.Notes -Split("\r\n") | ForEach {$Note = $_ -Split(":", 2); If ($Note[0].Trim()) {$My[$Note[0].Trim()] = $Note[1].Trim()}}
$My.Path = $My.File.FullName; $My.Folder = $My.File.DirectoryName; $My.Name = $My.File.BaseName
$My.Arguments = (($MyInvocation.Line + " ") -Replace ("^.*\\" + $My.File.Name.Replace(".", "\.") + "['"" ]"), "").Trim()
Example of $My object:
Name Value
---- -----
DESCRIPTION <Description goes here>.
EXAMPLE Example.ps1...
Name My
Folder C:\Users\User\Scripts\Test\PowerShell
Version 1.0.0.0 20160725 Initial Build
Author Glen Buktenica
NOTES Author : Glen Buktenica...
File C:\Users\User\Scripts\Test\PowerShell\My.ps1
Title <Synopsis goes here>.
Arguments -test
SYNOPSIS <Synopsis goes here>.
Path C:\Users\User\Scripts\Test\PowerShell\My.ps1
Contents <# ...
Help .SYNOPSIS ...
Assuming your NOTES section looks like this:
.NOTES
Version : 1.6.2
Author : Mary Doe
Created on : 2019-02-06
License : MIT License
Copyright : (c) 2019 Mary Doe
you can convert the note records into a hashtable variable with the help of this function:
function GetVersionInfo {
$notes = $null
$notes = @{}
# Get the .NOTES section of the script header comment.
$notesText = (Get-Help -Full $PSCommandPath).alertSet.alert.Text
# Split the .NOTES section by lines.
$lines = ($notesText -split '\r?\n').Trim()
# Iterate through every line.
foreach ($line in $lines) {
if (!$line) {
continue
}
$name = $null
$value = $null
# Split line by the first colon (:) character.
if ($line.Contains(':')) {
$nameValue = $null
$nameValue = @()
$nameValue = ($line -split ':',2).Trim()
$name = $nameValue[0]
if ($name) {
$value = $nameValue[1]
if ($value) {
$value = $value.Trim()
}
if (!($notes.ContainsKey($name))) {
$notes.Add($name, $value)
}
}
}
}
return $notes
}
Now, you can get version like this
$versionInfo = GetVersionInfo
$versionInfo["Version"]
Just remember to conform to the help about header requirements (must have it followed by at least one blank line, must have it at the top of the script, etc); otherwise, it will not work. Also, the function assumes that note entries are single line with colon (:) character delimiter.