Skip to content

Modules containing colliding names causes side-effects that are visible in other modules #12036

@alx9r

Description

@alx9r

The way that PowerShell resolves commands with colliding names seems to have changed sometime between PowerShell 5.1 and 7. The new behavior is problematic because it introduces the possibility of the following happening:

Invoking a command in one module can have the side effect that changes the command to which a different name in an unrelated module resolves.

In other words, (at least by default in PowerShell 7, it seems) one can never be sure that code invoked in a different module will not inadvertently change the command to which a name in your module will resolve.

This seems like something I need to take into careful account when designing modules. Accordingly, I'm hoping to find answers to the following questions:

  1. Is this the design intent of PowerShell? If so, how should modules be designed to prevent other modules from inadvertently changing the commands to which names resolve?
  2. Is there some way to override this behavior so that a module imported in one module doesn't appear in another?

Other notes:

Steps to reproduce

Create the following well-defined module q in $Env:PSModulePath:

# q.psd1
@{
    ModuleVersion     = '0.1.0'
    RootModule        = 'q.psm1'
    FunctionsToExport = 'Get-FileHash','q1'
}
# q.psm1
function Get-FileHash {}
function q1 {}

Invoke the following:

New-Module m {
    function m1 {
        [pscustomobject]@{
            Call        = $MyInvocation.MyCommand.Name
            CommandType = Get-Command Get-FileHash | % CommandType
            Module      = Get-Command Get-FileHash | % Module | % {[System.IO.FileInfo]::new($_.Path).Name}
        }
    }
    function m2 {q1} # this call should not alter the Get-FileHash that is visible in module p
} | Import-Module
New-Module p {
    function p1 {
        [pscustomobject]@{
            Call        = $MyInvocation.MyCommand.Name
            CommandType = Get-Command Get-FileHash | % CommandType
            Module      = Get-Command Get-FileHash | % Module | % {[System.IO.FileInfo]::new($_.Path).Name}
        }
    }
} | Import-Module

m1
p1
m2
m1
p1

Expected behavior

Either this behavior (which is how PowerShell 5.1 behaves)

Call CommandType Module
---- ----------- ------
m1      Function q.psm1
p1      Function q.psm1
m1      Function q.psm1
p1      Function q.psm1

or this behavior

Call CommandType Module
---- ----------- ------
m1        Cmdlet Microsoft.PowerShell.Utility.psd1
p1        Cmdlet Microsoft.PowerShell.Utility.psd1
m1      Function q.psm1
p1        Cmdlet Microsoft.PowerShell.Utility.psd1

Actual behavior

Call CommandType Module
---- ----------- ------
m1        Cmdlet Microsoft.PowerShell.Utility.psd1
p1        Cmdlet Microsoft.PowerShell.Utility.psd1
m1      Function q.psm1
p1      Function q.psm1

Environment data


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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Questionideally support can be provided via other mechanisms, but sometimes folks do open an issue to get aResolution-By DesignThe reported behavior is by design.WG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions