Automatically updating the version number in a PowerShell Module – How I do regex

I am presenting Continuous Delivery for your PowerShell Module to the PowerShell Gallery at PSDayUK in London. Go and register if you will be close to London on Friday 22nd September.

In 45 minutes we will

– Use Plaster to create our module framework
– Use GitHub for Version Control
– Use Pester to develop our module with TDD
– Use VSTS to Build, Test (with Pester) and Release our changes to the PowerShell Gallery

45 minutes will not give me much time to dive deep into what is done but I will release all of my code on GitHub.

One of the things I needed to accomplish was to update the version number in the module manifest file. I did this with some regex and this is how I achieved it.

I went to regex101.com and pasted in the contents of a module file into the test string box and start to work out what I need. I need the value after ModuleVersion = ‘ so I started like this

01 - regex101.png

Under the quick reference it has some explanations which will help you. Keep going until you have the correct value in the match information. In the image below you can see that it has a Group 1 in green which matches the value I want (0.9.13). There is also an explanation of how it has got there. This is what I shall use in the PowerShell script

01 - regex.png

Now we can go to PowerShell. First get the contents of the file

# get the contents of the module manifest file
try {
    $file = (Get-Content .\BeardAnalysis.psd1)
}
catch {
    Write-Error "Failed to Get-Content"
}

Then we use [regex]::matches() to get our value as shown below. I always like to write in the comments what the regex is doing so that I (or others) know what was intended. We also set the value to a type of Version. I reference the group 1 value that I saw in the website.

# Use RegEx to get the Version Number and set it as a version datatype
# \s* - between 0 and many whitespace
# ModuleVersion - literal
# \s - 1 whitespace
# = - literal
# \s - 1 whitespace
# ' - literal
# () - capture Group
# \d* - between 0 and many digits
# ' - literal
# \s* between 0 and many whitespace

[version]$Version = [regex]::matches($file, "\s*ModuleVersion\s=\s'(\d*.\d*.\d*)'\s*").groups[1].value

Next we need to add one to the version number

# Add one to the build of the version number
[version]$NewVersion = "{0}.{1}.{2}" -f $Version.Major, $Version.Minor, ($Version.Build + 1)

and then replace the value in the file, notice the Get-Content has braces around it

# Replace Old Version Number with New Version number in the file
try {
    (Get-Content .\BeardAnalysis.psd1) -replace $version, $NewVersion | Out-File .\BeardAnalysis.psd1
    Write-Output "Updated Module Version from $Version to $NewVersion"
}
catch {
$_
    Write-Error "failed to set file"
}

That’s how I do it and the process I use when I need regex!

Here is the full script

# get the contents of the module manifest file
try {
    $file = (Get-Content .\BeardAnalysis.psd1)
}
catch {
    Write-Error "Failed to Get-Content"
}

# Use RegEx to get the Version Number and set it as a version datatype
# \s* - between 0 and many whitespace
# ModuleVersion - literal
# \s - 1 whitespace
# = - literal
# \s - 1 whitespace
# ' - literal
# () - capture Group
# \d* - between 0 and many digits
# ' - literal
# \s* between 0 and many whitespace

[version]$Version = [regex]::matches($file, "\s*ModuleVersion\s=\s'(\d*.\d*.\d*)'\s*").groups[1].value
Write-Output "Old Version - $Version"

# Add one to the build of the version number
[version]$NewVersion = "{0}.{1}.{2}" -f $Version.Major, $Version.Minor, ($Version.Build + 1)
Write-Output "New Version - $NewVersion"

# Replace Old Version Number with New Version number in the file
try {
    (Get-Content .\BeardAnalysis.psd1) -replace $version, $NewVersion | Out-File .\BeardAnalysis.psd1
    Write-Output "Updated Module Version from $Version to $NewVersion"
}
catch {
$_
    Write-Error "failed to set file"
}

 

An easier way

My fabulous friend and MVP Ravikanth Chaganti has told me of a better way using Import-PowerShellDataFile

This command is available on PowerShell v5 and above. There is no need to use regex now 🙂 You can just get the manifest as an object and then use the Update-ModuleManifest to update the file

$manifest = Import-PowerShellDataFile .\BeardAnalysis.psd1 
[version]$version = $Manifest.ModuleVersion
# Add one to the build of the version number
[version]$NewVersion = "{0}.{1}.{2}" -f $Version.Major, $Version.Minor, ($Version.Build + 1) 
# Update the manifest file
Update-ModuleManifest -Path .\BeardAnalysis.psd1 -ModuleVersion $NewVersion

 

 

 

 

 

 

 

 

 

4 thoughts on “Automatically updating the version number in a PowerShell Module – How I do regex

  1. I was going to say, my god youre working hard to get the manifest 😁. I think Test-ModuleManifest does something similar to the import data file.

  2. i ran into the following weird problem:

    created a module
    c:\Users\Administrator\Documents\WindowsPowerShell\Modules\Toolbox\
    with two subfolders:
    \0.0.1\
    \0.0.2\

    in each folder i added:
    ToolBox.psd1
    ToolBox.psm1

    for folder 0.0.1 i edited the psd1 file

    # Script module or binary module file associated with this manifest.
    RootModule = ‘ToolBox’
    # Version number of this module.
    ModuleVersion = ‘0.0.1’

    and ofcourse
    # Script module or binary module file associated with this manifest.
    RootModule = ‘ToolBox’
    # Version number of this module.
    ModuleVersion = ‘0.0.2’

    the name of the module has to be the same as the folder name (same as RootModule)
    the module reads all the *.ps1 files in the folders
    \private\*.ps1
    \public\*.ps1

    when i would create a third new version (0.0.3) i would do the following if automated:
    make a copy of the latest version 0.0.2 and rename the folder 0.0.3
    \0.0.3\

    the contents of version 0.0.2 will be copied to 0.0.3

    when i edit manually the contents of the toolbox.psd1 file
    # Version number of this module.
    ModuleVersion = ‘0.0.2’ -> ModuleVersion = ‘0.0.3’
    everything goes fine and i can load it as the new version.

    however, if i have copied it and want to use the version number updater methode:
    $mod = c:\Users\Administrator\Documents\WindowsPowerShell\Modules\Toolbox\0.0.3\toolbox.psd1
    $manifest = Import-PowerShellDataFile $mod
    $manifest
    (shows version 0.0.2)
    then i would do:

    Update-ModuleManifest -Path $mod -ModuleVersion ‘0.0.3’

    and it raises an error:

    Update-ModuleManifest : Cannot update the manifest properly. ‘The ModuleVersion key in module manifest
    ‘C:\Users\Administrator\Documents\WindowsPowerShell\Modules\Toolbox\0.0.3\toolbox.psd1’ specifies module version ‘0.0.2’ which does not match its version folder name at
    ‘C:\Users\Administrator\Documents\WindowsPowerShell\Modules\Toolbox\0.0.3′. Change the value of the ModuleVersion key to match the version folder name.’
    At line:1 char:1
    + Update-ModuleManifest -Path c:\Users\Administrator\Documents\Windows …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (c:\Users\Admini….3\toolbox.psd1:String) [Update-ModuleManifest], ArgumentException
    + FullyQualifiedErrorId : InvalidModuleManifestFile,Update-ModuleManifest

    So to change the version i need to “Change the value of the ModuleVersion key to match the version folder name.”
    Powershell 5.1 on a windows 2012 R2 standard server.

    • I guess that makes sense, you are updating the version in the folder that you are using. I would separate the development of the code from the artefact that you are using

      I am updating the manifest in a folder provided from source control before zipping it up to publish to a PowerShell Repository.

      So I would perform the update on the code in source control and then publish it or copy it to the modules folder

  3. Thnaks for the quick reply. 🙂
    Im not updating the version that i am using: i still use the version (0.0.2) that is copy to a new one (0.0.3). I didn’t load the newly created module version. (import-module -force). All the other properties i can set.
    i now read the manifest (from current active module Import-PowerShellDataFile ) and create a new manifest (New-ModuleManifest) with all the same properties. and raising the module version.
    not bieng able to update the version number in this specific case feels more like a bug.

Please feel free to comment on this post. All comments are moderated first before appearing on the site

This site uses Akismet to reduce spam. Learn how your comment data is processed.