Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PowerShell Import-Module with .ps1 quirk.

PowerShell Import-Module with .ps1 quirk

Well, not so much a quirk - but an interesting anti-pattern I found in some (poor quality) PowerShell. Documenting the "how and why" so I can refer to it again if needed!

Example

We have two files callme.ps1 and functions.ps1:

functions.ps1:

function Magnetik-Function() {
	Write-Output "This is Magnetik-Function"
}

callme.ps1:

Import-Module -Name ($PSScriptRoot + "\functions.ps1")
Magnetik-Function

Note that callme.ps1 incorrectly uses Import-Module against a .ps1 file (not a module) - that's what exposes the quirk.

Running

PS Z:\> .\callme.ps1
This is Magnetik-Function
PS Z:\> .\callme.ps1
Magnetik-Function : The term 'Magnetik-Function' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At Z:\callme.ps1:5 char:1
+ Magnetik-Function
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Magnetik-Function:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

PS Z:\>

Weird? Why does Magnetik-Function() work once only?

  • When Import-Module is called in the first instance, functions.ps1 as a module doesn't exist - so the code is executed.
  • Executing functions.ps1 defines the function Magnetik-Function() in the scope of callme.ps1 and is able to be called successfully.
  • On the second and subsequent runs, the module functions is already known to PowerShell in this session - so is not re-run, thus Magnetik-Function() is never re-declared and we get failure.

We can also see this by a call to Get-Module:

PS Z:\> Get-Module

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        functions
Manifest   3.1.0.0    Microsoft.PowerShell.Management     {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Content...}
Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object...}


PS Z:\>

Note that functions as a module exists (it takes it's name from functions.ps1) - but because the file is not a true module (with a file extension of .psm1) it doesn't export any methods (functions).

In conclusion

  • If needing to bring in a .ps1 of functions/code - source them like so:

     . ($PSScriptRoot + "\functions.ps1")
  • When creating actual PowerShell modules, be sure to name such files correctly, with the right file extension - e.g. functions.psm1.

@stkb

This comment has been minimized.

Copy link

stkb commented Mar 20, 2018

Hope you won't mind me commenting here but I came here from google after experiencing this confusing behaviour myself.
This saved me a lot of time and headache so thanks!

@jakubin

This comment has been minimized.

Copy link

jakubin commented Jun 6, 2018

Great tip - thanks!

@timothies

This comment has been minimized.

Copy link

timothies commented Jun 12, 2018

Thank you for the illustration, it was well written and very useful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.