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
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
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=|,.*$'}}
Now to show the behavior in Windows 10 version 1511 which has PowerShell version 5.0 installed by default:
As you can see, the SkipPublisherCheck
parameter wasn't previously required:
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:
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
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
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.
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
Windows 10 version 1607:
Windows 10 version 1703:
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.
µ