Beware of the PowerShell Update-ModuleManifest Function
I recently presented a session for the Mississippi PowerShell User Group on
PowerShell Non-Monolithic Script Module Design.
While preparing for that session, I discovered that a problem I had previously experienced with
Update-ModuleManifest
when trying to update the FunctionsToExport
section when
FormatsToProcess
is specified appeared to be resolved in PowerShell version 5.1 (I'm running build
14393). The details of this bug can be found
here.
I also noticed that Nicholas Getchell had written about
this problem being resolved on his blog.
What I discovered is that Update-ModuleManifest
does a little too much updating which can cause
problems. To demonstrate this problem, I'll create a script module named MyModule containing the
following code:
1Get-ChildItem -Path $PSScriptRoot\*.ps1 -Exclude *.tests.ps1, *profile.ps1 |
2ForEach-Object {
3 . $_.FullName
4}
The previous code is saved as MyModule.psm1 in the following folder:
$env:ProgramFiles\WindowsPowerShell\Modules\MyModule
A function named Get-MrSystemInfo
is created:
1#Requires -Modules CimCmdlets
2function Get-MrSystemInfo {
3 Get-CimInstance -ClassName Win32_OperatingSystem |
4 Select-Object -ExpandProperty Caption
5}
That function is saved as Get-MrSystemInfo.ps1
in the same folder as the PSM1 file.
And finally a module manifest is created:
1New-ModuleManifest -Path $env:ProgramFiles\WindowsPowerShell\Modules\MyModule\MyModule.psd1 -RootModule MyModule -Author 'Mike F Robbins' -Description 'MyModule' -CompanyName 'mikefrobbins.com'
When designing modules with a non-monolithic approach and specifying a requires statement for a
module in one of the functions, as shown in the Get-MrSystemInfo
example, causes all of the
functions that are part of the specified module to show up as being part of your module.
In this scenario, the CimCmdlets are showing up as being part of MyModule:
1Get-Command -Module MyModule
I've written about this problem in
a previous blog article
and it's easy enough to resolve by removing the *
from the CmdletsToExport
section and replace
the *
in the FunctionsToExport
section of the module manifest with your actual function names.
The default settings in the module manifest that was previous created in this blog article:
1# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
2FunctionsToExport = '*'
3
4# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
5CmdletsToExport = '*'
6
7# Variables to export from this module
8# VariablesToExport = @()
9
10# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
11AliasesToExport = '*'
The problem is that when you run Update-ModuleManifest
to add the function name to FunctionsToExport
:
1Update-ModuleManifest -Path $env:ProgramFiles\WindowsPowerShell\Modules\MyModule\MyModule.psd1 -FunctionsToExport 'Get-MrSystemInfo'
It not only changes the *
in the FunctionsToExport
section of the manifest to the function name
that was specified, but it also updates CmdletsToExport
to contain all of the cmdlets contained in
the CimCmdlets module and it removes the '*' from the AliasesToExport
section of the manifest.
1# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
2FunctionsToExport = 'Get-MrSystemInfo'
3
4# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
5CmdletsToExport = 'New-CimInstance', 'Set-CimInstance', 'Get-CimSession',
6 'Get-CimInstance', 'Get-CimAssociatedInstance', 'Get-CimClass',
7 'New-CimSession', 'Remove-CimInstance', 'Remove-CimSession',
8 'New-CimSessionOption', 'Invoke-CimMethod', 'Export-BinaryMiLog',
9 'Register-CimIndicationEvent', 'Import-BinaryMiLog'
10
11# Variables to export from this module
12# VariablesToExport = @()
13
14# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
15AliasesToExport = @()
Update-ModuleManifest
had one action to perform and only one action which was to update the FunctionsToExport
section in the module manifest as previous specified.
To workaround this problem in this scenario, you can change CmdletsToExport
to @()
prior to
running Update-ModuleManifest
and it won't be changed. You could also specify the
CmdletsToExport
parameter with the @()
value when creating the module manifest to prevent this
problem from occurring.
My recommendation is not to use *
anywhere in your module manifest <period>
.
µ