Microsoft PowerShell module manifests allow you to define scripts that are run prior to actual loading of the module itself. These scripts run in the caller’s scope (and not in the module’s scope) and can be defined by stating them in the ‘ScriptsToProcess’ attribute of the manifest.
However, each of these scripts will appear as if they have been loaded as modules. You can verify this behaviour by issuing a ‘Get-Module’ after loading a module.
### part of the manifest file of 'biz.dfch.PS.Some.Module' # Script files (.ps1) that are run in the caller's environment prior to importing this module. ScriptsToProcess = @( 'Import-Module.ps1' ) ### loading the module Import-Module C:\PSModules\biz.dfch.PS.Some.Module\biz.dfch.PS.Some.Module.psd1 ### checking loaded modules PS > Get-Module ModuleType Name ExportedCommands ---------- ---- ---------------- Script biz.dfch.PS.System.Logging {Out-Message, Out-MessageAlert, Out-MessageCritical, Out- Script biz.dfch.PS.System.Utilities {ConvertFrom-Base64, ConvertFrom-CmdletHelp, ConvertFrom- Script Import-Module Manifest Microsoft.PowerShell.Management {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Co Manifest Microsoft.PowerShell.Security {ConvertFrom-SecureString, ConvertTo-SecureString, Get-Ac Manifest Microsoft.PowerShell.Utility {Add-Member, Add-Type, Clear-Variable, Compare-Object...}
This bug is documented by Kirk Munro on Microsoft Connect.
To easily and flexibly remove these ‘modules’ you can add the following script to your PSM1 module file:
[string] $ManifestFile = '{0}.psd1' -f (Get-Item $PSCommandPath).BaseName; $ManifestPathAndFile = Join-Path -Path $PSScriptRoot -ChildPath $ManifestFile; if( Test-Path -Path $ManifestPathAndFile) { $Manifest = (Get-Content -raw $ManifestPathAndFile) | iex; foreach( $ScriptToProcess in $Manifest.ScriptsToProcess) { $ModuleToRemove = (Get-Item (Join-Path -Path $PSScriptRoot -ChildPath $ScriptToProcess)).BaseName; if(Get-Module $ModuleToRemove) { Remove-Module $ModuleToRemove; } } }