3

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 }

1 Answer 1

6

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 calls Export-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 with Export-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.

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 call Export-ModuleMember, you'll also see the two-step process described above in action: Exporting ... lines preceding the Importing ... ones describe the implicit candidate exports.
  • To force an already imported module to be re-imported after modifying its definition, call Import-Module with the -Force switch.

Sign up to request clarification or add additional context in comments.

3 Comments

The explanation on the document mentioned above is rather obscure, and it will be much better with this document. learn.microsoft.com/zh-cn/powershell/module/…
regarding "as of PowerShell 7.2"; did the default behavior change? I have scripts that are no longer working & it seems like something changed here.
thanks. I must be doing something wrong. I posted a question here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.