[Bug] PowerShell Scripts in ScriptsToProcess attribute appear as loaded modules

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;
    }
  }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: