I’ve finally finished the first public release of PoshWpf, and was getting ready to ship it as part of a new release of my PowerBoots module. The idea is that I need PoshWpf itself to be a stand-alone module so that it can be used in production with PowerShell 1.0, until such time as PowerShell 2.0 goes gold, and we can get that into production use, so we can use PowerBoots. PowerBoots is a script module, and it uses dynamic parameters, so most of it can’t really be done in v1, but you can use PoshWpf as a snapin, including the New-PowerBoots cmdlet, to do asynchronous multi-threaded UIs like my “ping monitor demo.”
So I need to update the .psd1 Module Metadata file for PowerBoots to include PoshWpf … I read up on Oisin Grehan’s blog about the possible properties in the module manifest, and decide that I could do this by packaging PoshWpf as a NestedModule in PowerBoots. There’s not a whole lot of point in distributing PoshWpf as it’s own module — Version 1 users will need to install it as a Snapin anyway, since PowerShell 1.0 doesn’t support modules, and I expect PowerShell 2.0 users to use it with PowerBoots.
So I open up the PowerBoots.psd1 file, and add the line: NestedModules="PoshWpf" and fire up PowerShell and run Import-Module PowerBoots … and get this Error:
Import-Module : The module to process ‘PowerBoots’, listed in module manifest ‘C:\Users\Joel\Documents\WindowsPowerShell\Modules\PowerBoots\PowerBoots.psd1’ was not processed because no valid module was found in any module directory.
Now, I have no idea what that’s supposed to mean, except that I know the way that the PowerBoots.psm1 script gets parsed is that the PowerBoots.psd1 metadata includes a line: ModuleToProcess="PowerBoots.psm1" … I don’t know why the error doesn’t say “.psm1”, and I don’t know why that would be the error when what I added was the PoshWpf line, but I comment my line out and everything works, so I decide that maybe I need to say “PoshWpf.dll” (following the example that works of loading the PowerBoots script by specifying the full extension).
So I move PoshWpf.dll from it’s subdirectory right into the PowerBoots folder, and I change my line to: NestedModules="PoshWpf.dll" and fire up PowerShell and run Import-Module PowerBoots … and get this Error: Import-Module : An item with the same key has already been added.
Wow, I’m two for two: two attempts to load my module, two completely incomprehensible errors.
I noticed on Oisin’s site earlier that he mentioned something I didn’t know. There’s a RequiredModules property for module metadata, which I knew about, but although it will not try to load the module, Oisin’s post mentions that “this could optionally be done using a script in ScriptsToProcess” ... so I check that out.
I put PoshWpf.dll in it’s own Module folder: C:\Users\Joel\Documents\WindowsPowerShell\Modules\PoshWpf and I check that I can load it: Import-Module PoshWpf and then check that I can load PowerBoots: Import-Module PowerBoots. Success! Now to put in a script, with just that one line. I call it “PoshWpf.ps1” and put it the PowerBoots folder, and then add this line: ScriptsToProcess="PoshWpf.ps1" and … get another error Import-Module : The required module ‘PoshWpf’ is not loaded. Load the module or remove the module from ‘RequiredModules’ in the file ‘C:\Users\Joel\Documents\WindowsPowerShell\Modules\PowerBoots\PowerBoots.psd1’.
This time it’s obvious: despite what Oisin said, the script doesn’t run before the requirement is validated, so it doesn’t work the way I thought he meant. I switch the order of the lines around to see if it makes any difference, but it doesn’t. I decide that if I can just load the PoshWpf module, maybe I don’t care if it’s marked as “required” (it’s not technically required, you can still use Out-Boots — it’s just deprecated). So I comment out the requirement … and that works.
So at this point I’m almost ready to declare this a partial success and move on. But I’m an obsessive guy, and I don’t like the fact that people who don’t read this whole article won’t know how to get a list of all the PowerBoots modules (ie: they have to run Get-Command -Module PowerBoots, PoshWpf because the modules are completely separate, as far as PowerShell is concerned). So I really wanted to make it a nested module.
Somewhere around this point, I went to bed. When I woke up, I was having a conversation with someone on IRC that made me think of using @() notation…
So I went back to the beginning and try the line as: NestedModules=@("PoshWpf") but I still got the same error as before: Import-Module : The module to process ‘PowerBoots’, listed in module manifest ‘C:\Users\Joel\Documents\WindowsPowerShell\Modules\PowerBoots\PowerBoots.psd1’ was not processed because no valid module was found in any module directory. This time I got curious, so I ran it with -Debug and -Verbose on, and suddenly I was even more confused. The verbose output starts with the news that the loader is loading both PowerBoots.psd1 and PowerBoots.psm1, and then lists all of the functions created by PowerBoots.psm1 …
After a little digging, it’s clear that what they meant was that PoshWpf wasn’t being loaded … because PowerBoots itself is loaded fine. The error message is just completely wrong, and very frustrating. So now I’m thinking maybe I’m just not specifying the path to the nested module right…
I tried putting “.\PoshWpf” (since at this point I have PoshWpf in a subfolder of PowerBoots), and I got the old Import-Module : An item with the same key has already been added error again! Aarrgh
In frustration, I changed my profile to pre-set $VerbosePreference and $DebugPreference and $WarningPreference to “Continue” so that I could get as much information as possible (since I was having to restart PowerShell to be sure that the “item with the same key” error wasn’t fake). The next thing I tried was to set the full path to the dll: NestedModules="PoshWpf\PoshWpf.dll" and suddenly it seemed to work. The Verbose output included the exporint and importing of the cmdlets from PoshWpf … but I was still getting the “item with the same key” error at the end.
That made me kind-of curious, since the error appears to terminate loading, so to aid in debugging I commented out some code in my PowerBoots module, because that .psm1 file exports hundreds of functions, which makes it hard to tell exactly what’s happening… and discovered that the functions from PoshWpf.dll are being double-imported … so that’s probably what caused the duplicate key error. I try a few things, and finally resort to Set-PSDebug -Step …
Only to discover that when the PoshWpf.psd1 file says: ExportedCmdlets="Out-Wpf", the system seems to export and import all of the cmdlets… plus all the functions from the parent module that were already exported! I have no idea what’s going on, so I’m blogging, and contacting some MVPs, maybe they’ve seen more info than I have.
After talking to a couple people, it’s pretty clear that what I’m doing should work, but doesn’t. I switch back to my earlier attempt: move PoshWpf.dll into the root PowerBoots directory, and set the NestedModules="PoshWpf" … of course I get the same error as before, but this time I’m running in full verbose, debug and trace mode, and I can see that all the cmdlets are actually being loaded, but the script functions are being hit oddly.
In a fit of confusion I try commenting out my ModuleToProcess="PowerBoots.psm1" line, and I put the script module into the nested modules list: NestedModules="PoshWpf","PowerBoots.psm1" … and suddenly it just works. I uncomment the function generation in PowerBoots.psm1, and it appears we’re good to go. I can’t decide if this is a bug, or just a problem of missing documentation. In any case, loading bot the psm1 and dll as nested modules works, and causes all of the functions and cmdlets to show up when I run Get-Command -Module PowerBoots, which is really the important part. Case closed — I’ll just have to write up something on connect to see what the Microsoft team says about fixing these error messages and documenting how on earth we’re supposed to use module metadata.
God yes the module situation is really pretty vague right now. I’ve been unable to use ModuleToProcess at all. It feels “dirty” but most of my modules are set up as ModuleA\ModuleA.psd1, ModuleA\ModuleA.psm1 and the psd1 refers to the psm1 in the NestedModules attribute.
Seems totally wrong to me because psm1 is not a nested module… it is the module. But any other way and I run into problems very similar to what you describe.
Hi Joel, just wanted to say thanks for a great product. However I am having trouble with some basics. For example how do you use attached properties, in gridpanel and dockpanel. Will there be anymore boots tutorials to cover more of what this product can do?
Regards, Ken.
Attached properties are … not properly supported yet. I’ll write a post about how to do it “for now” and then I’ll think hard about how to do it in the future…