Freitag, 2. April 2010

PowerShell modules are funny guys (III)

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

Keine Kommentare:

Kommentar veröffentlichen