About updating inbox PowerShell modules

I’ve started testing Windows 10 1803 branch and got surprised by a few things.

First issue: Update-Module : Module ‘Pester’ was not installed by using Install-Module, so it cannot be updated

I wanted to get the latest version of Pester and naïvely ran:

Update-Module -Name Pester -Verbose

Ok, I hardly remember other MVPs talking about this problem…
To fix it ASAP, I did:

# Step 1: Save locally
Find-Module -Name Pester -Repository PSGallery -Verbose | 
Save-Module -Path  ~/Downloads -Verbose

# Step 2: remove alternate stream if any
dir ~/Downloads/Pester/* -rec -for -ea 0 | 
Unblock-File -Verbose

# Step 3: move to Programfiles
gi ~/Downloads/Pester/* | 
Copy-Item -Destination "C:\Program Files\WindowsPowerShell\Modules\Pester" -Recurse

NB: I moved it to programfiles because the Get-Module uses the PSModulePath environment variable to find and enumerate available modules. Keep that in mind. I’ll come back later on this.

The above longer way will actually prevent you from hitting a second road block if you try to take a shortcut.
Note that it’s also a best practice to review downloaded code before installing and trusting it.

Second issue:
PackageManagement\Install-Package : The version ‘4.3.1’ of the module ‘Pester’ being installed is not catalog signed.
Ensure that the version ‘4.3.1’ of the module ‘Pester’ has the catalog file ‘Pester.cat’ and signed with the same
publisher ‘CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US’ as
the previously-installed module ‘4.3.1’ with version ‘3.4.0’ under the directory ‘C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0’. If you still want to install or update, use -SkipPublisherCheck

Updating the module doesn’t work because it’s not installed from the PSGallery and is instead shipped inbox.
Let’s install it using Install-Module and not Update-Module. Right?

Find-Module -Name Pester -Repository PSGallery -Verbose | 
Install-Module -Verbose

Notice the above warning about the untrusted source.

Ok, don’t give up or be irritated, the solution and the shortcut is in the red error message 😛

Install-Module -Name Pester -Repository PSGallery -SkipPublisherCheck

One last step, you’re almost there. This time the fix is in the warning stream. You need a -Force.

Install-Module -Name Pester -SkipPublisherCheck -Force -Repository PSGallery 

With the 2nd issue illustrated, you probably understand why I go my way (using the 3 steps shown in issue #1 above)

Third issue: The installed module doesn’t show up!

No matter what I do, the installed module isn’t discovered by the Get-Module cmdlet although it’s located in one of the locations stored in the $env:PSModulePath variable:

Get-Module -Name Pester -ListAvailable
Get-Module -Name Pester -ListAvailable -Refresh
$env:PSModulePath -split ';'

The PowerShell prompt is elevated and running in constrained mode.


Applocker Allow mode (no default rules!) is preventing the new module from being discovered.
Because of the digital signature. The 3.4.0 is signed by Microsoft and the 4.3.1 isn’t signed at all

Get-AuthenticodeSignature 'C:\Program Files\WindowsPowerShell\Modules\Pester\*\*.ps?1'

How to fix this?
If you can, the best solution is to use an internal PKI and/or a code signing certificate to sign the 4.3.1 files. Then you just add a single Applocker rule to trust that Publisher.
There’s a second solution.

Fourth issue: an Applocker cmdlet shortcoming…
When you use the -Directory parameter, it doesn’t pick .psd1 and .psm1 files 😦

Get-AppLockerFileInformation -Directory 'C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1' -Recurse -FileType Script

You can for sure use the Get-AppLockerFileInformation cmdlet on PSD1 and PSM1 files

# Check psd1 and psm1 files
Get-AppLockerFileInformation 'C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\*.ps?1'

# Try to create a policy
Get-AppLockerFileInformation 'C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1\*.ps?1' |
New-AppLockerPolicy -User EveryOne

You can pipe the two cmdlets Get-AppLockerFileInformation and New-AppLockerPolicy but it creates an empty Applocker policy object 😦

Here’s my solution:

# Copy psd1 & psm1 files as ps1 files
dir 'C:\Program Files\WINDOWSPOWERSHELL\MODULES\PESTER\4.3.1\*.ps?1' -Recurse -Force | 
Foreach-Object { 
 $_ | Copy-Item -Destination "$($_.FullName).ps1"  

# Create a local policy using these 2 files
Get-AppLockerFileInformation -Directory 'C:\Program Files\WindowsPowerShell\Modules\Pester\4.3.1' -Recurse -FileType Script | 
New-AppLockerPolicy -User EveryOne -RuleNamePrefix 'Allow Pester 4.3.1' | 
Set-AppLockerPolicy -Merge -Verbose

Last but not least. Refresh the group policies.

Now, Pester 4.3.1 can be imported and used even in ConstrainedLanguage mode 😎


5 thoughts on “About updating inbox PowerShell modules

    • Thanks for reporting this link. The average admin/IT pro user experience is still awful and Microsoft has to fix this since it was reported repeatedly …

      • Yeah I wish that Github had an answer not just possible resolution/workaround. I knew about it because I just built two machines and first things I go for are Pester, PowerShellGet and Packagement before my script starts installing the third party modules I use. Script used to work.

      • And the ConstrainedLanguage thing is just now giving me grief as the company is now applying PowerShell lockdown. VSCode is really useless in this mode.

  1. Pingback: Dew Drop – May 7, 2018 (#2719) | Morning Dew

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s