I’m starting a new series of blog posts about Best Practices for scripting in PowerShell, and I was going to start at the beginning with a requirement that you should use [CmdletBinding()], but the explanation of that will have to wait for the next post, because a bug in PowerShell 2.0 has surfaced which can only be avoided by carefully following a couple of rules … and I’m going to issue those rules as the prefix for the best practices.
Rule #1: Never use Get-Module -ListAvailable in a module.
You need to run the command outside of your module. The simplest way to do that is to use Invoke-Command { Get-Module -List Available } … that should give you the same output, but without the nasty side effects.
There is a bug in the ListAvailable parameter, which causes PowerShell to mark other modules which are already loaded as being “nested” in your module.
It does that to all modules which have correct manifests, and the problem is that if your module gets unloaded later (using Remove-Module), it removes these nested modules as well … even though the user had loaded them separately.
Edit: 2010-08-05
I should have mentioned this originally (so I’m adding it now): one of the reasons developers were using Get-Module with -ListAvailable was to get information about their own module during the initial load (such as to check module versions, or load data from the PrivateData). If you were doing that, you can use Test-ModuleManifest instead with the path to your manifest: Test-ModuleManifest $PSScriptRoot\ModuleName.psd1
Rule #2: Do not use Import-Module in a module.
If you have a dependency on another module, you should load it by specifying it as a NestedModules in your module manifest.
There is a bug in the way that Remove-Module unloads modules which causes modules which are loaded from inside your module (whether by Import-Module or by Get-Module -ListAvailable), to be unloaded completely even if they’ve been previously loaded in the console (global) scope interactively by the user (or via their profile).
You could possibly make an exception to this rule, if the module is actually in your module’s folder (and thus, not easily loadable from outside your module), but you’re making the assumption that no one will ever use that module outside of your module.
Modules loaded via the metadata file’s NestedModules property don’t have this problem, so you should always load nested modules that way.