How to Use the PowerShell Gallery to Update Your Standalone Modules

Chris Wahl · Posted on2016-12-282020-05-06

I’ve been on a mission to migrate all of my commonly used PowerShell modules over to the PowerShell Gallery. This has a number of awesome benefits: easier upgrades using Upgrade-Module, the ability to enforce version control, and using the sync capabilities of OneDrive across my Windows devices. However, trying to use Update-Module on a module that was included with Windows or installed manually at an earlier date results in an error:

Update-Module : Module '{name}' was not installed by using Install-Module, so it cannot be updated.

Here’s an example using the Pester module as a reference. I have two versions installed in the Program Files directory. However, Update-Module is not able to help me because the module was not installed using Install-Module. The cmdlet knows this because the hidden PSGetModuleInfo.xml isn’t there.

To solve this, I’ve started doing two things:

Verified the OneDrive path as part of the PSModulePath environmental variable. This seems to be a natural part of using Windows 10. Check out this blog post for more details.

Use Install-Module with the -Scope CurrentUser parameter.

Installing Modules to the CurrentUser Scope

I made a number of mistakes trying to get this right, so I’ll share them here. The first command I tried was a simple installation with verbose logging.

Install-Module -Name Pester -Scope CurrentUser -Verbose

However, this throws an error.

WARNING: Version '3.4.0' of module 'Pester' is already installed at 'C:\Program
Files\WindowsPowerShell\Modules\Pester\3.4.0'. To install version '3.4.3', run Install-Module and add the -Force
parameter, this command will install version '3.4.3' in side-by-side with version '3.4.0'.

Fair enough! Let’s add the -Force switch.

Install-Module -Name Pester -Scope CurrentUser -Verbose -Force

The results are not happy, either. This time due to a signing error. Pester issue 585 explains the reason.

PackageManagement\Install-Package : The version '3.4.3' of the module 'Pester' being installed is not catalog signed.
Ensure that the version '3.4.3' 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 '3.4.3' 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
parameter.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:1772 char:21
+ ... $null = PackageManagement\Install-Package @PSBoundParameters
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (Microsoft.Power....InstallPackage:InstallPackage) [Install-Package],
Exception
+ FullyQualifiedErrorId : ModuleIsNotCatalogSigned,Validate-ModuleAuthenticodeSignature,Microsoft.PowerShell.Packa
geManagement.Cmdlets.InstallPackage

I’m not happy that I need to use -SkipPublisherCheck to circumvent a security measure, but it appears there’s no other way. Also, it seems that this is a one time necessity.

The final try succeeded and Pester version 3.4.3 (the latest at this time) is now installed.

Module Validation

Let’s check to make sure it’s in the OneDrive location, which is the location of my CurrentUser scope.

By importing the module, we can double check that the Pester module is being snagged from the correct location.

There! Now I can use Update-Module in the future to keep Pester up-to-date against the PowerShell Gallery. I’ve performed this workflow against many of my common modules such as ISESteroids, OperationValidation, PSSlack, Watchmen, and others. Because they are all sync’ed using OneDrive, I only have to perform the updates once and all of my devices will receive the new code.