Today I continue to write about some advanced features, you only touch when you are importing some modules and than to remove some of them again.
To demonstate I create two modules, the first to be used as submodule by the second. I call it mod_s
$script:state_s = 0
Write-host "Executing mod_s"
$mInfo = $MyInvocation.MyCommand.ScriptBlock.Module
$mInfo.OnRemove = { Write-Host "Removing module mod_s" }
function Get-State
{
return $script:state_s
}
function Set-State ($x)
{
$script:state_s = ($x)
}
function Set-ModSUnremovable
{
$mInfo = $MyInvocation.MyCommand.ScriptBlock.Module
$mInfo.AccessMode = "readonly"
}
function Set-ModSremovable
{
$mInfo = $MyInvocation.MyCommand.ScriptBlock.Module
$mInfo.AccessMode = "ReadWrite"
}
Se second is used to import this module, I call it mod_a:
Write-host "Executing mod_a"
Import-Module mod_s.psm1
Write-host "Old state $(Get-state)"
Set-state 11
function Get-StateA
{
return Get-State
}
function Set-StateA ($x)
{
Set-State $x
}
Now let us see what happens, when I first import mod_s and than mod_a and finally remove mod_s
1]10:33:45 C:\Var\bin (FileSystem)
ipmo mod_s
Executing mod_s
_____________________________________________________________________________________________________
[2]10:33:50 C:\Var\bin (FileSystem)
ipmo mod_a
Executing mod_a
Old state 0
_____________________________________________________________________________________________________
[3]10:33:57 C:\Var\bin (FileSystem)
rmo mod_a
Removing module mod_s
_____________________________________________________________________________________________________
[4]10:34:02 C:\Var\bin (FileSystem)
gmo
ModuleType Name ExportedCommands
---------- ---- ----------------
Script ISECreamBasic {get-AvailableModuleList, Remove-IseMenu, Add-IseMenu}
_____________________________________________________________________________________________________
[5]
Let us remember, that mod_s is removed and the global reference to mod_s is removed.
Next let us keep a referenc to mod_s before removing mod_a:
[1]10:39:04 C:\Var\bin (FileSystem)
ipmo mod_s
Executing mod_s
_____________________________________________________________________________________________________
[2]10:40:52 C:\Var\bin (FileSystem)
$a = gmo mod_s
_____________________________________________________________________________________________________
[3]10:40:58 C:\Var\bin (FileSystem)
ipmo mod_a
Executing mod_a
Old state 0
_____________________________________________________________________________________________________
[4]10:41:03 C:\Var\bin (FileSystem)
rmo mod_a
Removing module mod_s
_____________________________________________________________________________________________________
[5]10:41:07 C:\Var\bin (FileSystem)
$a
ModuleType Name ExportedCommands
---------- ---- ----------------
Script mod_s {Set-ModSUnremovable, Set-State, Set-ModSremovable, Get-State}
_____________________________________________________________________________________________________
[6]10:41:12 C:\Var\bin (FileSystem)
gmo
ModuleType Name ExportedCommands
---------- ---- ----------------
Script ISECreamBasic {get-AvailableModuleList, Remove-IseMenu, Add-IseMenu}
_____________________________________________________________________________________________________
[7]
Here you see, that mod_s doesn't execute its termination code. I get the impression, that they use some sort of reference count to modules and when it drops down to 0. The module gets unloaded from memory.
The fact that the reference to the global scope is removed, by removing a submodul makes it difficult to ensure that some modules are imported.
Lets study
Bruce Payette. He has a section Controlling when modules can be unloaded.
Let's try:
[1]10:49:09 C:\Var\bin (FileSystem)
ipmo mod_s
Executing mod_s
_____________________________________________________________________________________________________
[2]10:49:15 C:\Var\bin (FileSystem)
Set-ModSUnremovable
_____________________________________________________________________________________________________
[3]10:49:23 C:\Var\bin (FileSystem)
Set-ModSremovable
_____________________________________________________________________________________________________
[4]10:49:30 C:\Var\bin (FileSystem)
Set-ModSUnremovable
_____________________________________________________________________________________________________
[5]10:49:39 C:\Var\bin (FileSystem)
ipmo mod_a
Executing mod_a
Old state 0
_____________________________________________________________________________________________________
[6]10:49:45 C:\Var\bin (FileSystem)
rmo mod_a
Remove-Module : Unable to remove module 'mod_s' because it is read-only. Use the -force flag to remove r
ead-only modules.
At line:1 char:4
+ rmo <<<< mod_a
+ CategoryInfo : PermissionDenied: (mod_s:PSModuleInfo) [Remove-Module], InvalidOperationE
xception
+ FullyQualifiedErrorId : Modules_ModuleIsReadOnly,Microsoft.PowerShell.Commands.RemoveModuleComman
d
_____________________________________________________________________________________________________
[7]10:49:49 C:\Var\bin (FileSystem)
Set-ModSremovable
The term 'Set-ModSremovable' is not recognized as the name of a cmdlet, function, script file, or operab
le program. Check the spelling of the name, or if a path was included, verify that the path is correct a
nd try again.
At line:1 char:18
+ Set-ModSremovable <<<<
+ CategoryInfo : ObjectNotFound: (Set-ModSremovable:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
_____________________________________________________________________________________________________
[8]
Anyone not calling this a bug around ?
Bernd