Powershell: Import-Module: incorrect scope, confusing parameters, wrong documentation?

Created on 19 Nov 2017  路  18Comments  路  Source: PowerShell/PowerShell

I am not sure what but something is wrong:

  • If the documentation is correct then Import-Module imports to the wrong scope by default, global.

    • Then this is a bug in Import-Module, probably tough to fix (breaking).

  • If the documentation is wrong and the default is global then:

    • The documentation should be corrected.

    • The switch Global is rather confusing in this case.

Steps to reproduce

MyModule.psm1

function MyFunc {
    'MyFunc'
}
Export-ModuleMember -Function MyFunc

test1.ps1

Import-Module "$PSScriptRoot\MyModule.psm1" #-Scope Local
MyFunc

test2.ps1

& "$PSScriptRoot\test1.ps1"
MyFunc

Expected behavior

If the documentation is correct then I expect test2.ps1 to fail with "MyFunc
is not found" because test1.ps1 imports the module to the default local
scope.

Actual behavior

test2.ps1 works and calls MyFunc successfully.

Guess about actual behavior

If we uncomment -Scope Local in test1.ps1 then test2.ps1 fails "MyFunc
is not found". That means that the default scope is not local, as the help says.

Quotes from help

-Scope <String>
    Specifies a scope into which this cmdlet imports the module.

    The acceptable values for this parameter are:

    - Global . Available to all commands in the session. Equivalent to the
      Global parameter.

    - Local . Available only in the current scope.

    By default, the module is imported into the current scope, which could be a
    script or module.

-Global [<SwitchParameter>]
    Indicates that this cmdlet imports modules into the global session state so
    they are available to all commands in the session. By default, the commands
    in a module, including commands from nested modules, are imported into the
    caller's session state. To restrict the commands that a module exports, use
    an Export-ModuleMember command in the script module.

    The Global parameter is equivalent to the Scope parameter with a value of Global.

Environment data

I observe this in v5 and v6-rc

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

Name                           Value
----                           -----
PSVersion                      6.0.0-rc
PSEdition                      Core
GitCommitId                    v6.0.0-rc
OS                             Microsoft Windows 10.0.15063
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Issue-Question

Most helpful comment

@nightroman @mklement0
I can't repro the condition, when you use -Scope Local from the script.
What I see, is that when you use Import-Module cmdlet from script or scriptblock, it always imports into the global scope.

TheModule.psm1

function TheFunction
{
    Write-Output -InputObject 'I am TheFunction.'
}
Remove-Module TheModule -Force
& {Import-Module .\TheModule.psm1}
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
& {Import-Module .\TheModule.psm1 -Scope Global}
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
& {Import-Module .\TheModule.psm1 -Scope Local}
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-198e967e208e04eb28a6a483240fb6df



Import-Module $PSScriptRoot\TheModule.psm1



md5-1a7030985d3de87372721b2cde68810c



Import-Module $PSScriptRoot\TheModule.psm1 -Scope Global



md5-fd1c2f177a141b3e7ff5aadaef4849ae



Import-Module $PSScriptRoot\TheModule.psm1 -Scope Local



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
.\import_default.ps1
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
.\import_global.ps1
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
.\import_local.ps1
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-82136b91dab73d0b169cf97caff10399



Import-Module $PSScriptRoot\TheModule.psm1

function Get-TheModule
{
    Get-Module TheModule
}

Export-ModuleMember -Function Get-TheModule



md5-b59073196c5af86b9596f6e3f3f42401



Import-Module $PSScriptRoot\TheModule -Scope Global

function Get-TheModule
{
    Get-Module TheModule
}

Export-ModuleMember -Function Get-TheModule



md5-6215cf80e1cc2e16f91cc27f1a0c0996



Import-Module $PSScriptRoot\TheModule -Scope Local

function Get-TheModule
{
    Get-Module TheModule
}

Export-ModuleMember -Function Get-TheModule



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
Import-Module .\import_default_Module.psm1
Get-TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction

Get-Module TheModule
# nothing returned

Remove-Module import_default_Module -Force



md5-aca6c8c665159181185625f080dab5d6



Import-Module .\Import_global_Module.psm1
Get-TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction

Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction

Remove-Module Import_global_Module -Force
Remove-Module TheModule -Force



md5-aca6c8c665159181185625f080dab5d6



Import-Module .\Import_local_Module.psm1
Get-TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction

Get-Module TheModule
# nothing returned

Remove-Module Import_local_Module



md5-cf241fa6115539bbea1f7360c87e81e7



Name                           Value
----                           -----
PSVersion                      6.1.0-preview.748
PSEdition                      Core
GitCommitId                    6.1.0-preview.748
OS                             Microsoft Windows 10.0.17134
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

All 18 comments

The issue was labeled Issue-Question. I have taken a look at other items in this category. I do not think this issue is a question. It does not ask anything. It describes the bug, either in the cmdlet or the documentation.

@nightroman we use that label until it has been confirmed as a bug by a knowledge area expert.

Oh, I am sorry then, I did not know. Other issues in that category looked like true questions, that's why I worried.

Good analysis, @nightroman - I took the liberty of creating a docs issue (that links) here: https://github.com/PowerShell/PowerShell-Docs/issues/2691, as it is safe to assume that the global-by-default behavior won't change and that it is therefore the docs that should be corrected.

Aside from fixing the docs, the implications for the code base are:

  • Since -Global serves no useful purpose, as you state, do we have a way of _deprecating_ parameters, e.g. by hiding them from tab completion?

  • Is it worth introducing a -Local switch instead? It may be overkill, given that current-scope-only imports are probably not that common (just a guess).

@nightroman @mklement0
I can't repro the condition, when you use -Scope Local from the script.
What I see, is that when you use Import-Module cmdlet from script or scriptblock, it always imports into the global scope.

TheModule.psm1

function TheFunction
{
    Write-Output -InputObject 'I am TheFunction.'
}
Remove-Module TheModule -Force
& {Import-Module .\TheModule.psm1}
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
& {Import-Module .\TheModule.psm1 -Scope Global}
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
& {Import-Module .\TheModule.psm1 -Scope Local}
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-198e967e208e04eb28a6a483240fb6df



Import-Module $PSScriptRoot\TheModule.psm1



md5-1a7030985d3de87372721b2cde68810c



Import-Module $PSScriptRoot\TheModule.psm1 -Scope Global



md5-fd1c2f177a141b3e7ff5aadaef4849ae



Import-Module $PSScriptRoot\TheModule.psm1 -Scope Local



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
.\import_default.ps1
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
.\import_global.ps1
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
.\import_local.ps1
Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction



md5-82136b91dab73d0b169cf97caff10399



Import-Module $PSScriptRoot\TheModule.psm1

function Get-TheModule
{
    Get-Module TheModule
}

Export-ModuleMember -Function Get-TheModule



md5-b59073196c5af86b9596f6e3f3f42401



Import-Module $PSScriptRoot\TheModule -Scope Global

function Get-TheModule
{
    Get-Module TheModule
}

Export-ModuleMember -Function Get-TheModule



md5-6215cf80e1cc2e16f91cc27f1a0c0996



Import-Module $PSScriptRoot\TheModule -Scope Local

function Get-TheModule
{
    Get-Module TheModule
}

Export-ModuleMember -Function Get-TheModule



md5-aca6c8c665159181185625f080dab5d6



Remove-Module TheModule -Force
Import-Module .\import_default_Module.psm1
Get-TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction

Get-Module TheModule
# nothing returned

Remove-Module import_default_Module -Force



md5-aca6c8c665159181185625f080dab5d6



Import-Module .\Import_global_Module.psm1
Get-TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction

Get-Module TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction

Remove-Module Import_global_Module -Force
Remove-Module TheModule -Force



md5-aca6c8c665159181185625f080dab5d6



Import-Module .\Import_local_Module.psm1
Get-TheModule

ModuleType Version Name      ExportedCommands
---------- ------- ----      ----------------
Script     0.0     TheModule TheFunction

Get-Module TheModule
# nothing returned

Remove-Module Import_local_Module



md5-cf241fa6115539bbea1f7360c87e81e7



Name                           Value
----                           -----
PSVersion                      6.1.0-preview.748
PSEdition                      Core
GitCommitId                    6.1.0-preview.748
OS                             Microsoft Windows 10.0.17134
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

@sethvs: Thanks for digging deeper:

Re script behavior:

You must distinguish between _a module's visibility to Get-Module_ and the _availability (importing) of its exported members_.

A -Scope Local-imported module in a child scope still shows up in an ancestral scope's Get-Module output, but its exported members aren't _callable_ there, because they weren't _imported_.

While it may seem curious that the module shows up in Get-Module's output, the import still is _local_ in the sense that no ancestral scopes can _use_ the module, because it doesn't get _imported_.

Thus, the real test for the locality of an import is to try to _invoke an exported member_ from another scope.

A quick example:

PS> & { 'function f1{"[f1]"}'>t1.psm1; ipmo -Scope Local ./t1.psm1; f1 }; f1; gmo t1
[f1] # ok: callable from the local scope
f1 : The term 'f1' is not recognized as the name of a cmdlet, function, script file, or operable program.
...

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        t1                                  f1

As you can see, the calling scope doesn't see the exported f1 _function_ (because it was imported with -Scope Local into the _child_ scope only), but Get-Module does see the t1 _module_.

Re nested-modules behavior:

Good catch: When a module imports another module, Import-Module effectively defaults to -Scope Local, and the same applies to modules loaded implicitly via the NestedModuleKeys in a module's manifest (*.psd1).

Note that it's generally better to import nested modules via a _manifest_, and that you then _invariably_ get the local behavior.

Separately, though, you're free to _export_ the nested module's locally imported exported members _as part of the parent module_ - simply by referencing them in Export-ModuleMember calls or, preferably, via the FunctionsToExport, AliasesToExport, and VariablesToExport keys in a module manifest.
(A minor pitfall is that if your parent module relies on the default export behavior - where _all_ functions and aliases are exported - the functions and aliases among the _nested_ module's exported members are automatically _included_ - however, a module generally shouldn't rely on implicit export behavior.)


That leaves just one case in which -Global / -Scope Global actually makes a _difference_, though its usefulness is questionable:

If a _module_ uses an explicit Import-Module -Globalcall to import another module, that other module indeed becomes globally available.
However, unless I'm missing something, a module should never import another module globally behind the user's back.


So, in summary:

  • From a _non-module_ scope, Import-Module:

    • is global by default
    • can be made local with -Scope Local
  • From a _module_ scope, Import-Module:

    • is local by default (it's up to the parent module what, if anything, to _export_)
    • can, but _shouldn't_ be made global with -Global / Scope -Global
    • Generally, it's worth _discouraging explicit use of Import-Module in modules_ in favor of declaring nested modules via a _manifest_.

Given that we've arrived at these findings by trial and error, perhaps a subject-matter could review the findings. @SteveL-MSFT, would you mind looking at this, assigning someone?

I haven't looked at the PR that was just submitted, but I strongly suspect it needs revising now;
cc @sdwheeler

@BrucePay can you confirm @mklement0's explanation matches design intent?

@mklement0
about script behavior.
Interesting finding.
What is Import-Module cmdlet is doing: is importing some module and exporting it's content (functions, aliases, etc.) into the scope.

Concerning calling Import-Module -Scope Local from inside the script, is imports a module into global scope, and it's content - in the script scope. It looks more like a bug, then the lack of documentation.

Joining the request to @BrucePay :)

@sethvs

What Import-Module cmdlet is doing: is importing some module and exporting it's content (functions, aliases, etc.) into the scope.

I would phrase that differently:

  • Import-Module is _loading_ a module (on demand),
  • and then _importing_ the module's _exported members_ (there's never any exporting _to_ - its always an act of _importing_ on the part of the code that wants to use module's exported members)

It is only the _importing_ that can be scoped, and arguably that is all that matters.

Note that the current documentation and terminology conflate the aspects of _loading_ and _importing_ - notably in the term _auto-loading_ - which it arguably shouldn't:

While you can't _only_ load a module, you can prevent its getting _imported_ into _other scopes_ by using -Scope Local.

Get-Module sees that the module is _loaded_ globally - which happens irrespective of the specifics of the Import-Module call - but that is not a problem in practice (and irrelevant from the perspective of scope-limiting _importing_ it).

It may be awkward that a given scope may see the fact that a module is _loaded_ while not having access to its exports (not having imported them), if the Import-Module call was performed in a different scope with -Scope Local, but I don't see a _bug_ there.

@mklement0
It's not just awkward - it is inconsistent when some part of the functionality takes place in the global scope, and some - in local.

I'm OK with different defaults, when using cmdlet from script or scriptblock and from inside the module - Global and Local, respectively.
But when you use Import-Module -Scope Local it should not mean please load the module globally, and import it's content locally, I believe.

@sethvs:

You're right: it's an inconsistency if you expect Get-Module to list _imported_ modules (by default) - and that's certainly what its help topic claims [update: it's only an inconsistency if you assume imported into the _current scope_, which the topic does _not_ claim - see below].

Currently, it is reporting _loaded_ modules whose exports may or may not be available in the _current_ scope.

it should not mean please load the module globally, and import it's content locally

To be clear: what I'm suggesting is that this is more likely a Get-Module issue, not an Import-Module issue.

In a way it's pointless to call a module "globally loaded", because that state of being _loaded_ has no direct relationship with _scopes_.

Clearly, Get-Module knows about all _loaded_ modules (with a module getting implicitly loaded either via auto-loading or via an Import-Module call in _any_ scope) and has access to them independently of scopes.

Similarly, Remove-Module has access to all _loaded_ modules, and therefore allows removal ("unimporting" _and_ unloading) even of modules that were locally imported into a different scope.
(There may be additional inconsistencies / bugs lurking: calling Remove-Module on a module that was imported with -Scope Local from the same scope truly seems to only "unimport" from that scope, while the same module loaded into the global scope continues to work - yet Get-Module doesn't show it any longer.)

Clearly, this fuzziness around loaded vs. imported is problematic:

  • If we modified Get-Module and Remove-Module to only show / allow removal of modules that are either _imported into the current scope_ or _globally imported_, we'd have a breaking change on our hands.

  • Conversely, with the status quo, there's no way to relate Get-Module and Remove-Module to the current scope. That is, Get-Module's output doesn't let you determine whether a given module's exports are _available_ in the current scope, - only whether the module is _loaded_.
    This could be problematic if, say, you use Get-Module Foo in your code to indirectly test the availability of Foo's _commands_ in the current scope: if the module is loaded, but only because it was imported _locally_ into a _different_ scope, the test will not work as expected (testing for a specific _command_ with Get-Command would work, however).

Arguably, _both_ perspectives are valuable: knowing which modules are _loaded_ vs. which ones are _available in the current scope_ (imported locally into the current scope or globally imported).

Let's hear what Bruce has to say.

Technically, there are two things that you need to keep in mind when trying to figure out modules: scope and session state. By default, modules are loaded into the top-level of the current _session state_ not the current _scope_. If you are in the global scope (i.e. not in a module) then they get loaded into the global session state and any exports are placed into the global tables. If you load a module from _within_ a module, things are loaded into the _module's_ session state, not the global session state and any exports are placed at the top of the module's session state. If you use -Scope local, then the exports are placed into the current scope object rather than at the top level. If you are _in a module_ and use -Scope global (or -Global) to load another module, that module and it's exports will be loaded into the global session state object instead of the module's local session state. This feature was designed for writing module that manipulate modules (and is used by the WindowsCompatibility module to import proxy modules into the global scope.) Looking at the documentation snippet out of context

By default, the module is imported into the current scope, which could be a
script or module.

it does appear to be incorrect and should probably say "By default. the module is imported into the current session state, which could be a module session state or the global session state."

Thanks, @BrucePay - good to learn about the role of session states in this context.

However, given that _session state_ is not a well-known concept (and given that the only session-related conceptual topics, about_PSSession andabout_PSSession_Details are of little help and focus on sessions in the context of _remoting_; as an aside: they deserve a fundamental overhaul), I fear that:

By default. the module is imported into the current session state, which could be a module session state or the global session state

will not be helpful to the average user, not least because the parameters that modify the behavior relate to _scopes_.

I think what may make sense to the average user is the following:

  • _Outside_ of a module: Import-Module imports modules _globally_ by default:

    • That is, the top-level scope and all its descendant scopes (and even loaded modules) have access to the module's exported elements - even if Import-Module was called from a _descendant_ scope.

    • In a descendant scope, -Scope Local can be used to limit importing to that scope and all its descendant scopes. (Therefore, using -Scope Local in the top-level scope would make no difference). That is, parent scopes then do _not_ see the imported members.

    • Since session-global import is the default behavior, use of -Global / -Scope Global is pointless outside of a module.

    • If importing a module should include its class and enum definitions as well, use using module instead of Import-Module, and place it at the very beginning of your script

  • _Inside_ of a module: Import-Module imports another module _into that module only_ by default - non-module code and other modules don't see it (again, using -Scope Local in the top-level scope of the module would make no difference).

    • A better alternative to calling Import-Module from a module is to declare the target module as a _nested_ module via the module's own _manifest_ - this helps with discovering dependencies.

      • However, there may still be cases where explicit Import-Module calls are appropriate, such as when a dependent module cannot be assumed to always be there.
    • Either way, you may in turn export (public) members of the imported module by including them in the parent module's own exports.

    • Use -Global / -Scope Global, which makes the module available session-globally (to non-module code and to other modules), only in exceptional cases, given that modules should generally avoid session-global modifications on import.

      • However, a legitimate use case is to write modules expressly designed to manipulate modules loaded session-globally, such as the WindowsCompatibility module.

The above covers Import-Module only. Does that make sense and is it accurate enough?

Thanks for explanation, @BrucePay. Suspected something like this after looking through the code.

After thinking further about @BrucePay's explanation, I've revised the overview in my previous comment to (hopefully) present a pragmatic summary:

  • with a view to _practical implications_ of the behaviors.
  • with some _guidance_ as to when to use which features / parameters.

While as such it doesn't fit into the Import-Module help topic, I hope it provides a useful _basis_ for revising it.


I'll address the Get-Module / -Scope Local discrepancy separately, below.

Re the Get-Module / -Scope Local discrepancy (Get-Module potentially seeing a module even if it wasn't imported into the current scope):

In short: Unlike what I thought earlier, the help topics do _not_ support the expectation that Get-Module see only modules imported into the _current scope_, so a small amendment to the existing Get-Module help topic is probably sufficient (see below).
In other words, @sethvs: I don't think there was a problem to begin with, it was just a matter of framing things correctly, after all, though the amendment proposed below may help.

Some background on loading vs. importing (do tell me if I didn't get this right):

_Loading_ a module - into the enclosing session state - happens _implicitly_ the first time a module is imported (whether implicitly or explicitly), and subsequent imports of the same module reuse the already loaded module.

With the default behavior, loading the module entails making its exported members available to _all_ scopes of the session state (via inheritance from the top scope), so that all scopes both see the module with Get-Module _and_ see the imported members (though you can _restrict_ what members to import with the -Function, -Alias, and -Variable parameters).

The discrepancy can only arise with -Scope Local: ancestral scopes in the same session state then do _not_ see the _imported members_; however, they do see _the module itself_ in the Get-Module output, because Get-Module (by default) lists modules solely based on whether they're _loaded_ or, to put it differently, were imported into _any_ scope in the current session state, not whether or not their exported members happen to be imported into the current _scope_.

Similarly, Remove-Module cmdlet also targets _loaded_ modules and therefore too sees modules even in scopes in the same session state that happen not to have _imported the module's exports_.
(Perhaps needless to say, Remove-Module unloads the module _and_ removes its import.)


As for possible tweaks to the Get-Module topic:

Both the Get-Module and the Remove-Module help topics already mention the _current session_ as the entity whose imported modules are shown / whose imported modules are removed.
(The term _session_, unfortunately, is a bit nebulous - I'll address that separately).

Thus, arguably no promise is made that such a module must have been imported into the _current scope_ in order to be targeted, and no change is needed.

However, it may be worth adding a note to the NOTES section that explains that even though a given _scope_ may not have imported a given module's exports, a call to Get-Module will still show that module, as long as it was imported into _any_ scope in the same session.

As for what appears to be an actual _bug_ with -Scope Local that I've alluded to earlier: see #7349

I've created a new issue, #9582, which obsoletes #7349 and more generally, discusses the problems with invariably global module caching / removal vs. local importing.

Re the need to document the concepts of internal session states and to give them more descriptive official names, I've opened https://github.com/MicrosoftDocs/PowerShell-Docs/issues/4288

Was this page helpful?
0 / 5 - 0 ratings