Issue
From How to Write a PowerShell Module Manifest I learned that I can export all the variables in the module using VariablesToExport = '*'
. However, after using it, I found that I could not export any variables.
After writing tests to confirm and reading more documentation, I didn't find the cause of the problem. I may have overlooked something important. What is going on here?
TestModule.psm1
excerpt:
0..9 | ForEach-Object { New-Variable -Name "v_$_" -Value $_ }
TestModule.psd1
excerpt:
@{ModuleVersion = '1.0';RootModule = 'TestModule.psm1';VariablesToExport = '*'}
TestModule.Tests.ps1
:
# Confirm that the module has indeed been imported.
$ModuleName | Get-Module | ForEach-Object 'name' | Should -Be $ModuleName
# All variables do not exist.
0..9 | ForEach-Object { "variable:v_$_" | Test-Path | Should -BeFalse }
Solution
It is far from obvious, but, as of PowerShell 7.2, in order to export variables from a PowerShell module, listing them in the module manifest's (*.psd1
file's) VariablesToExport
entry alone is not enough:
You also need an Export-ModuleMember
-Variable
call in your script module file (*.psm1
) - be sure to place it at the end of the file, to ensure that all definitions to be exported have already been made.
Caveat:
- Once a
*.psm1
module callsExport-ModuleMember
, all definitions to be exported must be exported explicitly; that is,-Function
,-Cmdlet
, and-Alias
arguments must also be specified, as appropriate; in all cases, wildcard*
can be used to specify all definitions of the given type, and more specific wildcard name patterns may be used too.
E.g., to export all your $v_*
variables, as well as all functions matching the name pattern *-Foo*
, place the following at the bottom of your *.psm1
file:
Export-ModuleMember -Variable v_* -Function *-Foo*
Important:
With a module that has a module manifest (*.psd1
) - as is typical - and a script module (*.psm1
), the export logic is a two-step process:
Candidate export definitions are all those definitions exported from the
*.psm1
itself - either implicitly, or explicitly withExport-ModuleMember
statements.Implicit exports - i.e. automatic exports performed in the absence of
Export-ModuleMember
calls - comprise all functions and aliases, but not variables.Curiously, for dynamic modules - in-memory modules created with
New-Module
- it is functions only.
The export-relevant manifest (
*.psd1
) entries -FunctionsToExport
,AliasesToExport
,VariablesToExport
(CmdletsToExport
only applies to binary cmdlets exported from assemblies) - further filter down these candidate exports and the filtered results are a module's effective exports.- Note: As the comments in newly generated module manifests advise, wildcard patterns such as
'*'
, should be avoided in manifests, because they slow command discovery for auto-loading modules down; definitions should be enumerated explicitly, by their full names.
- Note: As the comments in newly generated module manifests advise, wildcard patterns such as
Debugging tips:
To see which definitions a given module exports, call
Import-Module
with the-Verbose
switch.- The
Importing ...
lines are the exported definitions being imported into the caller's scope. - If the
*.psm1
file does not callExport-ModuleMember
, you'll also see the two-step process described above in action:Exporting ...
lines preceding theImporting ...
ones describe the implicit candidate exports.
- The
To force an already imported module to be re-imported after modifying its definition, call
Import-Module
with the-Force
switch.
Answered By - mklement0 Answer Checked By - Robin (PHPFixing Admin)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.