Remove Class from Memory in PowerShell Remove Class from Memory in PowerShell powershell powershell

Remove Class from Memory in PowerShell


The Known Issue

There is a known issue in PowerShell 5.0 and 5.1 that explains this behavior. The issue was acknowledged by DongBo Wang on the PowerShell 6 team in November 2016. He wrote the following:

"The module analysis result is stored in a cache with the module file path as the key and the PSModuleInfo object as the value. The cache entries are not properly invalidated based on the LastWriteTime of the module file, and thus same cached value got reused."

In other words, PowerShell 5.0, 5.1, and 6.0 keeps (and uses) old copies of classes in memory when it shouldn't.

Implications

This issue causes considerable problems for development using PowerShell classes if you do not compensate for it. I wrote a test that covers about 100 of the scenarios where class reloading is important. Vaguely speaking, in about 17 of those scenarios PowerShell 5.0 and 5.1 doesn't reload the class when it should. This means using the same session across edits creates a real likelihood the interpreter will have cached duplicate copies of the same or similar classes. That makes behavior unpredictable and causes strange results that cannot be troubleshot.

Workaround

I have found that you can still be productive developing using PowerShell classes. You just need to perform each test run in a fresh PowerShell session when a project involves PowerShell classes whose source the PowerShell interpreter may consider to have changed. The customary way to do this is to invoke your test command from your PowerShell console by invoking powershell.exe:

powershell.exe -Command { Invoke-Pester }

That's not a terribly inefficient test-edit-test cycle if you've got tight unit tests. If you need to step through code, you'll need to launch a fresh copy of ISE each time you make an edit.

With this workaround, I have found the productivity impact of this bug to be manageable. I developed this and this entirely using this workaround. Each of those projects involve a significant amount of code involving PowerShell classes.