简体   繁体   中英

How can I use a PowerShell module in a script without leaving the module loaded in the user's session?

I have a script I wish to use interactively from the PowerShell prompt. The script needs to use a local script module.

I cannot see how to import/use the module such that it's not left loaded in the current session.

Example

A module (MyModule.psm1)...

function Test-Method
{
    write-host "Test-Method invoked"
}

... and a script (script.ps1)

Import-Module .\MyModule
Test-Method

Now running the script at the PowerShell prompt ...

PS C:\temp> Get-Module | % {$_.Name}
Microsoft.PowerShell.Management
Microsoft.PowerShell.Utility

PS C:\temp> .\script.ps1
Test-Method invoked

PS C:\temp> Get-Module | % {$_.Name}
Microsoft.PowerShell.Management
Microsoft.PowerShell.Utility
MyModule

How can my script import and use MyModule.psm1 without it being left loaded in the caller's current session? Bearing in mind that the call may have already imported the module and would not want it unloaded by the script (so simply removing the module at the completion of the script is not really good enough).

I've considered dot-sourcing the module rather than importing it, but I want the module for the reasons covered in PowerShell Import-Module vs Dot Sourcing

It sounds like you already described in pseudo-code what you wanted. Here it is in actual code:

$checkCmds = Get-Commands -Module MyModule

Import-Module MyModule

# Do stuff here . . .

# unload only if we loaded it
if ($checkCmds -eq $null) { Remove-Module MyModule }

As far as I can tell, you don't get that automatic cleanup behavior from a "script" importing a module. OTOH if you import a module from within another module, when the parent module is removed then any modules it imported will be removed if there are no other modules using them (or unless ipmo -global was specified).

This builds on the previous answer and uses the following property.

If you import a module from within another module, when the parent module is removed then any modules it imported will be removed

You can exploit several techniques to create a wrapper:

  • Importing a module from a module
  • Anonymous modules
  • Call operator with the context of a module

Set script.ps1 to

& (New-Module {
    function Invoke-Function {
        Import-Module .\MyModule
        Test-Method
    }
}) { Invoke-Function }

If you run script.ps1 and then (Get-Module).Name then MyModule will not be listed in the output.

Note: In this example Invoke-Function is just another scope, and can be omitted, letting the New-Module just run when defined. In one line:

& (New-Module { Import-Module .\MyModule; Test-Method }) {}

You can import the module with -Scope local to restrict a module to your script's scope. If the module happens to also be loaded in the global scope, then it will still be available after your script exits.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM