PowerShell icon indicating copy to clipboard operation
PowerShell copied to clipboard

Export-ModuleMember does not export functions when -Function parameter is used

Open maciejw opened this issue 3 years ago • 2 comments

Prerequisites

Steps to reproduce

assuming you have a module with psd1 and psm1 file as follows

TestModule.psd1

@{
    RootModule        = "TestModule2.psm1"
    ModuleVersion     = "0.0.1"
}

TestModule2.psm1

function Test-Function {
}
function Test-Function2 {
}
function Test-Function3 {
}

Export-ModuleMember -Function "Test-Function2", "Test-Function3"

Expected behavior

when we use Test-ModuleManifest we should see a list containing "Test-Function2", "Test-Function3"
like this

C:\>pwsh -NoProfile -Command Test-ModuleManifest C:\modules\TestModule2\TestModule2.psd1

ModuleType Version    PreRelease Name                                ExportedCommands
---------- -------    ---------- ----                                ----------------
Script     0.0.1                 TestModule2                         {Test-Function2, Test-Function3}

but it does not work like this.



### Actual behavior

```console
instead we see all 3 functions Test-Function, Test-Function2, Test-Function3


C:\>pwsh -NoProfile -Command Test-ModuleManifest C:\modules\TestModule2\TestModule2.psd1

ModuleType Version    PreRelease Name                                ExportedCommands
---------- -------    ---------- ----                                ----------------
Script     0.0.1                 TestModule2                         {Test-Function, Test-Function2, Test-Function3}

this works correctly on Windows PowerShell 5.1

I can make it work on PowerShell core, but I have to change how functions are exported as follows

Export-ModuleMember "Test-Function2", "Test-Function3"

I have to remove -Function parameter name

then it works on both windows powershell 5.1 and powershell core 7.2.5

also I could not find any info that Export-ModuleMember parameters have to be static.

my investigation started when I wanted to pass a variable with functions I want to export.

this idea with variable will not work, I get it, but Export-ModuleMember should work like docs describe, which is not the case currently. docs currently show -Function.

also since Export-ModuleMember has to be static why even bother with it? to me its the main use case for it, lets say I cannot use static list in psd1 file, then I could use dynamic list in psm1 file and use Export-ModuleMember. now in order to mane it work I have to specify statically this list, so I could do this in psd1 file.

I know why you do this, this would have impact on performance of module autoloading, but on the other hand why not put big exclamation in Export-ModuleMember docs



### Error details

_No response_

### Environment data

```powershell
powershell core on windows

$PsVersionTable
Name                           Value
----                           -----
PSVersion                      7.2.5
PSEdition                      Core
GitCommitId                    7.2.5
OS                             Microsoft Windows 10.0.19044
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

windows powershell

$PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.19041.1682
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.1682
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1



### Visuals

_No response_

maciejw avatar Jul 20 '22 16:07 maciejw

Export-ModuleMember will only work as you expect if you omit the psd1 module spec entirely. From memory, module exports work something like this:

  • If you don't use any Export-ModuleMember in the module psm1, then a psd1 module spec file will determine the exported functions via its FunctionsToExport key.
  • If you do use Export-ModuleMember and you have a psd1, then you must also name all of the functions that you want exported in the psd1 as well. You can't omit the FunctionsToExport just because you've used Export-ModuleMember.
    • The odd thing here is that if you use Export-ModuleMember in the psm1, then the psd1 can only export functions that have also been exported with Export-ModuleMember.
  • If you omit the psd1 file then the Export-ModuleMember statements are solely responsible for what functions are exported from the module.

This behaviour and interaction between Export-ModuleMember and a PSD1 file with a module is fairly non-obvious and I'm unsure if it's fully documented.

vexx32 avatar Jul 20 '22 19:07 vexx32

@vexx32 it does not work the way you've described it in second bullet. if you have psd1 you can omit FunctionsToExport you can put * there, it does not matter, you don't have to put any function names there, if you have Export-ModuleMember in psm1 it takes precedence, as long as you set it like I've describe in my issue, which is not consistent with documentation examples.

maciejw avatar Jul 22 '22 14:07 maciejw

The 3rd bullet point is not working for me either.

cxc256 avatar Sep 23 '22 18:09 cxc256

A year later, I've also run into this issue on PowerShell 7.3.6. This is still a problem.

han44-illinois avatar Sep 08 '23 19:09 han44-illinois