6

I have a class in the PowerShell module file. (A.psm1)

class A  {

    [void] printString() {
        write-host 111
    }

}

And I also have a simple script that uses that class.

Using module C:\temp\A.psm1

$a = [A]::new()
$a.printString()  # prints 111

But if I change the method from the class, for example, as shown here (replace 111 on 222)

[void] printString() {
     write-host 222
}

and if I relaunch my script it will still print 111. Only if I restart the PowerShell console it will print the new value. If I worked only in the console, I could use the Import-Module ... -Force command. But it doesn't work in the script.

So is there a way to reload the PowerShell module every time the script is launched without restarting the console itself?

2 Answers 2

8

This unfortunate behavior is a well-known issue, and as mklement0 points out no real good solution exist at the moment.

The underlying cause is a bit convoluted (part of the reason the behavior persists after 5+ years), but it's basically a 3-way conflict between:

  • Module lifecycle management in PowerShell (modules are supposed to be reloadable)
  • Type definition lifecycle management in .NET (a type can never be "un-defined" for the lifetime of the process*)
  • The way using module provides parse-time resolution of custom types - its not a particularly mature feature to put it plainly

Although no good solution exists, the VSCode PowerShell extension has a configuration option allowing you to run debug sessions in a temporary shell, making it a non-issue:

enter image description here

{
  "powershell.debugging.createTemporaryIntegratedConsole": true
}

Once set, you can use the following workflow for testing/debugging:

  1. Open the script in the editor
  2. Run it via the debugger (Shift+Ctrl+D -> Run and Debug)
  3. Observe printString() prints 111
  4. Make changes to the module file, save it
  5. Run the script via the debugger again
  6. Observe printString() now prints the new value
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! The workaround in VS Code suits my needs!
@АртурГудиев Great to hear, you're welcome! FWIW this is also how I develop modules with classes :-)
5

As far as I know, there's no good solution, unfortunately (as of PowerShell 7.2): The using module statement - which is the prerequisite for also loading classes from a module - has no equivalent to the Import-Module's -Force switch for forcing reloading of a module.

Workaround:

# (Force-re)load the module and get a reference to the module.
# This does NOT give you access to the classes defined in the module.
$module = Import-Module C:\temp\A.psm1 -PassThru -Force

# Use the module reference to execute code *in the module's* context,
# where the class *is* defined, so you can obtain a reference to the
# [A] class (type) this way:
$classA = & $module { [A] }

$classA::new().printString()
  • As you can see, this requires modifying the source code.

  • If you're using Visual Studio Code with the PowerShell extension, you can avoid this, as shown in Mathias R. Jessen's helpful answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.