Powershell: Import-Module foo.psm1 should still process foo.psd1 if exists

Created on 6 Aug 2018  路  11Comments  路  Source: PowerShell/PowerShell

Was talking to @jpsnover about this. It seems that if the module manifest exists, we should process that even if the user explicitly imported only the psm1. The problem is that depending on what the user imports, the result may not be what the module author intended. Unless the module author has matching FunctionsToExport in psd1 and Export-ModuleMember in psm1, the resulting exported members may be different (applies to other type and not just functions).

Steps to reproduce

New-ModuleManifest -Path foo.psd1 -FunctionsToExport foo1 -RootModule foo.psm1
Set-Content -Path foo.psm1 -Value @"
  function foo1 { "foo1" }
  function foo2 { "foo2" }
"@

Import-Module ./foo.psd1
Get-Command -module foo

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        foo1                                               0.0.1      foo

Import-Module ./foo.psm1 -Force
Get-Command -module foo       

Expected behavior

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        foo1                                               0.0.1      foo

Actual behavior

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        foo1                                               0.0        foo
Function        foo2                                               0.0        foo

Environment data

Name                           Value
----                           -----
PSVersion                      6.1.0-preview.4
PSEdition                      Core
GitCommitId                    6.1.0-preview.4
OS                             Darwin 17.7.0 Darwin Kernel Version 17.7.0: Thu Jun 21 22:53:14 PDT 2018; root:xnu-4570.71.2~1/RELEASE_X86_64
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Committee-Reviewed Documentation Needed Issue-Enhancement Up-for-Grabs WG-Engine

Most helpful comment

@PowerShell/powershell-committee reviewed this and do not agree with importing the psd1 when the user explicitly specified the psm1. We do agree that explicitly importing a psm1 when a psd1 exists is a development time scenario so we propose adding a warning when importing the psm1 and a psd1 exists.

All 11 comments

Sometimes I import the psm1 by design as a convenience to test the functions that are not 'public' (i.e. exported), should we therefore have an option for still being able to do that?

@bergmeister You can still copy the module and remove psd1 file for your test.

I'm not sure on the perceived benefit of this. In most cases modules should be in one of the PSModulePaths and therefore Import-Module by Name will import based on PSD1 by default if it's there and if not PSM1. T

This is expected and designed behaviour, behaviour that as teachers of how to properly use PowerShell we should be pushing people to use the language in the right way in the mass majority of cases. This means that if you want to explicitly import the PSM1 where a PSD1 exists, you would see this as an advanced use case like @bergmeister mentions above and the suggestion that @iSazonov has made can be definitely followed i'm not sure that this is ideal.

Therefore, IMO, this is a change that isn't sensible, and one that is not really required considering the why that things are set up like at present.

@SteveL-MSFT - the problem goes away using a moraccepted correct import method, ieImport-Module -Name MyModulewhereMyModule` exists in one of the PSModulePaths

This is more an education issue, both to end users and Module Authors, than being PowerShell Engine Issue.

We could turn on this only in strict mode.

It seems that if the module manifest exists, we should process that even if the user explicitly imported only the psm1.

@stevel-msft Could you elaborate on this? It's not obvious to me why such behavior is desirable.

If the module manifest exists, it should be the "source of truth" for the module. Intent by the author (for end users) is to import the module manifest which defines not only what functions/cmdlets/aliases/etc.. get exported, but also the formatting and types files to use. Importing the .psm1 directly won't give same experience (unless explicitly coded to do) and could give different behavior as nested modules or requiredassemblies wouldn't be processed.

In the dev scenario, it would still make sense to import the psd1 since they authored it and should want to validate the end user experience.

I can see how importing the psd1 when the user explicitly imported the psm1 could be surprising.

Another thought is to import always by name but allow psm1 only with "-Force".

Going to new major 7.0 version allow us to implement the "unlikely breaking" change.

@SteveL-MSFT this behaviour is because you've force imported the psm1 after importing the psd1.

The correct way to do this is to use Remove-Module on the psd1 and then import the psm1, and vice versa just like as @bergmeister mentions for development testing.

Because this is already the way it's designed and understood this way I don't think this change should really be considered for 7.0 at all because in reality this doesn't bring any realy additional value or benefit to either Module Dev's or End Users.

Even more so when you consider that good module development practices would not have a module being worked on in one of the PSModulePaths but a released version should be tested within one of these paths to ascertain that it works as intended in a user installed scenario.

I think there's better areas to investigate than what would be a breaking change and one that I personally cannot see the value from making this change, other than perhaps it highlighting a need for improved documentation around the Module development process, including authoring a recommended practice.

@PowerShell/powershell-committee reviewed this and do not agree with importing the psd1 when the user explicitly specified the psm1. We do agree that explicitly importing a psm1 when a psd1 exists is a development time scenario so we propose adding a warning when importing the psm1 and a psd1 exists.

I believe we need to document this explicitly.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andschwa picture andschwa  路  3Comments

ajensenwaud picture ajensenwaud  路  3Comments

manofspirit picture manofspirit  路  3Comments

JohnLBevan picture JohnLBevan  路  3Comments

garegin16 picture garegin16  路  3Comments