PowerShell PackageManagement and PowerShellGet Module Changes in Windows 10 Version 1511, 1607, and 1703

Recently, I reloaded my computer and noticed a problem when I tried to install the latest version of the Pester PowerShell module using PowerShellGet. I loaded Windows 10 version 1703 (the creators update) which has PowerShell version 5.1 installed by default:

1Get-CimInstance -ClassName Win32_OperatingSystem -Property Caption, BuildNumber, OSArchitecture |
2Select-Object -Property @{label='Operating System';expression={$_.Caption}},
3                        @{label='Version';expression={Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name ReleaseId}},
4                        BuildNumber,
5                        OSArchitecture
6
7$PSVersionTable.PSVersion

module-publisher-check1b.jpg

Pester version 3.4.0 ships with both Windows 10 version 1607 and 1703. Both of these versions of Windows and/or PowerShell seem to work differently than previous versions when updating and/or installing modules using PowerShellGet as shown in this blog article. I wouldn't necessarily call this a problem, it seems more like increased security, but it negates the effectiveness of the Force parameter in some cases.

The first error when I tried to run Update-Module to update the Pester module is expected since it wasn't originally installed using Install-Module, although it would have been nice of Microsoft to install it that way so updating would have been a little easier.

With Windows 10 version 1511, running Install-Module with the Force parameter installs the updated module without a problem, but beginning with Windows 10 1607, it generates an error because Pester version 3.4.0 is signed by Microsoft and the versions in the PowerShell Gallery are either not signed or are signed by a different publisher.

1Get-Module -Name Pester -ListAvailable
2
3Update-Module -Name Pester -Force
4
5Install-Module -Name Pester -Force
6
7Install-Module -Name Pester -Force -SkipPublisherCheck
8
9Get-Module -Name Pester -ListAvailable

module-publisher-check2a.jpg

 1PackageManagement\Install-Package : The version ‘4.0.5’ of the module ‘Pester’ being installed is not catalog signed.
 2Ensure that the version ‘4.0.5’ of the module ‘Pester’ has the catalog file ‘Pester.cat’ and signed with the same
 3publisher ‘CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US’ as
 4the previously-installed module ‘4.0.5’ with version ‘3.4.0’ under the directory ‘C:\Program
 5Files\WindowsPowerShell\Modules\Pester\3.4.0′. If you still want to install or update, use -SkipPublisherCheck parameter.
 6At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:1809 char:21
 7+ … $null = PackageManagement\Install-Package @PSBoundParameters
 8+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 9+ CategoryInfo : InvalidOperation: (Microsoft.Power….InstallPackage:InstallPackage) [Install-Package], Exception
10+ FullyQualifiedErrorId : ModuleIsNotCatalogSigned,Validate-ModuleAuthenticodeSignature,Microsoft.PowerShell.PackageManagement.Cmdlets.InstallPackage

Let's see who signed the modules to verify the previous errors are valid:

1Get-Module -Name Pester -ListAvailable -PipelineVariable Module |
2Select-Object -Property @{label='FilePath';expression={$_.Path}} |
3Get-AuthenticodeSignature |
4Format-Table -AutoSize -Wrap -Property @{label='Name';expression={$Module.Name}},
5                                       @{label='Version';expression={$Module.Version}},
6                                       Status,
7                                       @{label='SignedBy';expression={$_.SignerCertificate.Issuer -replace '^.*O=|,.*$'}}

module-publisher-check3b.jpg

Now to show the behavior in Windows 10 version 1511 which has PowerShell version 5.0 installed by default:

module-publisher-check4b.jpg

As you can see, the SkipPublisherCheck parameter wasn't previously required:

module-publisher-check5a.jpg

1Update-Module : Module ‘Pester’ was not installed by using Install-Module, so it cannot be updated.
2At line:1 char:1
3+ Update-Module -Name Pester -Force
4+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5+ CategoryInfo : InvalidOperation: (Pester:String) [Write-Error], WriteErrorException
6+ FullyQualifiedErrorId : ModuleNotInstalledUsingInstallModuleCmdlet,Update-Module

Pester version 3.3.5 instead of version 3.4.0 ships with Windows 10 version 1511 so I thought there might be some differences with the signatures, but they're the same:

module-publisher-check6a.jpg

I originally thought that maybe the PackageManagement or PowerShellGet module had changed, but both of those are at version 1.0.0.1 on Windows 10 version 1511, 1607, and 1703. Be sure to read the update at the end of this blog article.

I'm also seeing subtle differences when trying to install a module that includes commands that already exist on your system. On Windows 10 version 1511 with PowerShell 5.0, the PowerShell Community Extensions module installs with no problem:

1Get-Command -Name GCB
2
3Install-Module -Name Pscx -Force

module-publisher-check7a.jpg

On Windows 10 version 1607 or 1703, it complains about needing to use the AllowClobber parameter because a command in the Pscx module already exists on the system (That same command also existed in version 1511).

1Get-Command -Name GCB
2
3Install-Module -Name Pscx -Force
4
5Install-Module -Name Pscx -Force -AllowClobber

module-publisher-check8a.jpg

1PackageManagement\Install-Package : A command with name ‘gcb’ is already available on this system. This module ‘Pscx’
2may override the existing commands. If you still want to install this module ‘Pscx’, use -AllowClobber parameter.
3At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:1661 char:21
4+ … $null = PackageManagement\Install-Package @PSBoundParameters
5+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6+ CategoryInfo : InvalidOperation: (Microsoft.Power….InstallPackage:InstallPackage) [Install-Package], Exception
7+ FullyQualifiedErrorId : CommandAlreadyAvailable,Validate-ModuleCommandAlreadyAvailable,Microsoft.PowerShell.Pack
8ageManagement.Cmdlets.InstallPackage

I don't have a problem with the increased security, but my complaint is that whatever changes Microsoft has made, while great for security are breaking changes and has effectively rendered the Force parameter useless for the cmdlets shown in this blog article. When Force is specified, it means remove all safeties because I know what I'm doing and I don't care if you have to burn my system to the ground if that's what it takes to make it so. In other words, the Force parameter should override the need for the SkipPublisherCheck and/or the AllowClobber parameter in the scenarios shown in this blog article.

updated.jpg

I decided to perform a little more testing after noticing the line numbers in the error messages shown in this blog article were different depending on whether or not the command was run on Windows 10 version 1607 or 1703. I also decided to republish this blog article with different title to reflect the results of this further testing.

It appears what has happened to cause these differences, is that the PackageManagement and PowerShellGet modules have indeed been changed between Windows 10 versions and their module version numbers haven't been updated which made tracking down the source of the differences a little more difficult.

Windows 10 version 1511:

1Get-ChildItem -Path (Get-Module -Name PowerShellGet, PackageManagement -ListAvailable).ModuleBase

module-publisher-check9b.jpg

Windows 10 version 1607:

module-publisher-check10b.jpg

Windows 10 version 1703:

module-publisher-check11b.jpg

The file dates could be different and still be the same file, but the sizes are different which is a dead giveaway that something somewhere has changed.

µ