Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 717
Mark Wright Avatar asked Sep 30 '13 23:09

Mark Wright


People also ask

Are PowerShell modules installed per user?

The Install-Module uses the Name parameter to specify the PowerShellGet module. The RequiredVersion parameter specifies that version 2.0. 0 is downloaded and installed for all users.

How do I permanently import a PowerShell module?

To import PowerShell modules permanently you can copy them creating a folder on C:\Windows\system32\WindowsPowerShell\v1. 0\Modules\ with the name of your script, then inside you can put all your psm1 or ps1 files.

How do I use a PowerShell module?

How to Import a Module into Every Session. The Import-Module command imports modules into your current PowerShell session. To import a module into every PowerShell session that you start, add the Import-Module command to your PowerShell profile. For more information about profiles, see about_Profiles.


3 Answers

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 }
like image 131
Michael Sorens Avatar answered Nov 03 '22 01:11

Michael Sorens


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).

like image 22
Keith Hill Avatar answered Nov 03 '22 00:11

Keith Hill


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 }) {}
like image 30
maxwellb Avatar answered Nov 03 '22 02:11

maxwellb