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 }
Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
Andy
  • 1,077
  • 1
  • 8
  • 20

1 Answers1

4

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.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    The explanation on the document mentioned above is rather obscure, and it will be much better with this document. https://learn.microsoft.com/zh-cn/powershell/module/microsoft.powershell.core/new-modulemanifest?view=powershell-7.1 – Andy Aug 31 '21 at 09:28
  • 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. – spottedmahn Aug 02 '22 at 00:40
  • 1
    thanks. I must be doing something wrong. I posted a [question here](https://stackoverflow.com/questions/73215604/powershell-module-export-variables). – spottedmahn Aug 03 '22 at 02:16