PSCX 2.0 Cleanup & Modularization

Topics: Developer Forum, Project Management Forum
Sep 30, 2009 at 4:33 PM

Hi guys, I feel PSCX got a little bit too complex and maybe a bit bloated, too. I just deleted some unfinished work of mine that has been dragged along for far too long. 

I'd also like to split PSCX into more assemblies and modules, as I'm sure many people rarely use the DirectoryServices, MSMQ or ADO stuff. What do you think?

And another question - shall we upgrade to .NET 3.5 already?

Sep 30, 2009 at 11:50 PM

Our current plan, and is what I'm working on, is to split up Pscx into a smallish PscxLegacy (or something like that) that holds the cmdlets that duplicate what is now in PowerShell 2.0.  Other than that I don't see a real need to break it up further.  In 1.2 we did quite a bit of work to eliminate a number of automatic things like automatically creating an AD drive which was a mistake in retrospect.  Carrying that code around in the main module doesn't seem that onerous to me. 

BTW, make sure you are working trunk\src.  I branched 1.2 into the Releases dir.  Trunk has been changed significantly.  I note that because you have a quite a few files checked out (ie in limbo).  And I already deleted a number of the work in progress projects you had (ProfileUpdateApp, Console stuff, etc).  I also nuked the Setup project because we are going to be Module based in 2.0.  Before you change much, please make sure you have done a get latest and you might want to drop a number of your locks.

Sep 30, 2009 at 11:52 PM
Edited Oct 2, 2009 at 5:02 PM

Regarding .NET 3.5, I think even PowerShell 2.0 only requires .NET 2.0.  I don't think PSCX is in a position to force .NET 3.5 on folks.  When PowerShell requires .NET 3.5 then we should definitely jump on board with 3.5.  I do miss LINQ.

Oct 1, 2009 at 12:31 AM

You're right regarding .NET. ISE and Out-GridView obviously require 3.5, but the main part that is automatically installed with server Windows is still 2.0-based.

I just removed two my workspaces from machines that I don't even own anymore, and I deleted some other unused unfinished stuff. I'm working in trunk, don't worry :)

Splitting the assembly further probably isn't a good idea, but I think it would be nice to have functionality groupped into nested modules. Mainly for better code organization; I'm now adding the ConvertTo-Metric command, which comes with type and format data, and an alias. I would like to have a separate SIUnits module included by the main Pscx.psd1, rather than make four separate changes to it.

Oct 1, 2009 at 1:33 AM

Cool!  BTW I wonder if we should dynamically create the PSD1 file or just use "*" for functions, cmdlets, aliases, etc.  I guess the advantage of filling in the data explicitly is that you can find out the contents of a module without loading it.  Thoughts?

Oct 1, 2009 at 2:23 AM
Edited Oct 1, 2009 at 2:30 AM

I put together a shelveset "modular pscx" to show the idea. 

Basically, it goes like this: 

  • script-only features are implemented using .psm1 files (eg. Modules\Pscx.VHD.psm1); nothing interesting to see here
  • binary-only features are implemented using a .psd1 file which nests the Pscx.dll, only exporting selected commadlets & processing format and type data (eg. Modules\Pscx.Net.psd1)
  • binary features that need some supporting script, for example to set up aliases, have a .psm1 module that imports the .psd1 module, sets up aliases and stuff, and exports everything (eg. Modules\Pscx.SIUnits-Aliases.psm1)
  • and then there's the Modules\Pscx.psd1 (\ModularPscx.psd1 now), that references all the other modules

This arrangement has the advantage that the user can either simply import the whole Pscx.psd1, or can choose to pick only the modules they need. It's great for us too, as the modules are tiny and can be modified easily.

Any thoughts?

Oct 1, 2009 at 3:40 AM
This sounds great.  Being able to just load the cmdlets that I actually have a use for would be a plus in my book (and I imagine even more of a plus for others).

I'm a little confused about the psm1 that imports a psd1 (that sounds backwards), but I haven't found the time to look at what you're actually doing there.
Oct 1, 2009 at 4:03 AM

afaik, powershell 2.0 ISE implies .net 3.0 (i.e. wpf) but not 3.5, so no c# 3.0 compiler.



Oct 1, 2009 at 4:14 AM
Well, right now, PowerShell 2.0 RTM implies .net 3.5 SP1, since you can't get it down-level, right? ;-)
Oct 1, 2009 at 11:51 AM

ISE requires 3.5, perhaps even 3.5SP1, but it's not installed on Windows Server by default, so we're stuck with 2.0.

Jaykul, I tried it the other way first, but it makes no sense. The psd1 imports the core functionality - cmdlets, format & type data. The psm1 adds aliases and functions, and thus depends on the psd1. Also it makes sense to only import the psd1 without the aliases, not the other way round.

Oct 1, 2009 at 12:15 PM

I think I'm gonna create a separate branch, try to split up a few modules and we shall see if it's feasible.

Oct 2, 2009 at 1:16 AM

I found only one little issue so far: the providers are exported from the binary module automatically. The problem is that they need the format data to be usable, so I thought we'd change the GAC and Feed providers not to create the default drives, and move the drive creation into modules that would also load the format and type data. That way the advanced user wouldn't see any semi-broken drives if he choose not to load the respective module, while keeping the standard user experience the same.

Any thoughts?

PS D:\bits\Pscx-Mod\Src\PscxSnapin\bin\Debug> ipmo .\Modules\Pscx.psd1
WARNING: Some imported command names include unapproved verbs which might make them less discoverable.  Use the Verbose
parameter for more detail or type Get-Verb to see the list of approved verbs.
PS D:\bits\Pscx-Mod\Src\PscxSnapin\bin\Debug> D:\ps1\Recurse-Module.ps1

Module                     Type     Exports
------                     ----     -------
Pscx                       Manifest {cvxml, fxml, lorem, mail...}
  Pscx.DirectoryServices   Manifest {Get-DomainController, Get-DhcpServer, Get-ADObject}
  Pscx.Drawing             Manifest {Resize-Bitmap, Export-Bitmap, Import-Bitmap}
  Pscx.Math+Aliases        Script   {rnd, Get-Random, log10, pow...}
    Pscx.Math              Manifest {Get-Random}
  Pscx.Messaging           Manifest {Test-MSMQueue, Get-MSMQueue, New-MSMQueue, Clear-MSMQueue}
  Pscx.Net+Aliases         Script   {mail, ping, Resolve-Host, Ping-Host...}
    Pscx.Net               Manifest {Resolve-Host, Ping-Host, Get-HttpResource, Send-SmtpMail}
  Pscx.SIUnits+Aliases     Script   {metric, ConvertTo-Metric}
    Pscx.SIUnits           Manifest {ConvertTo-Metric}
  Pscx.TabExpansion+Enable Script   {TabExpansion}
    Pscx.TabExpansion      Manifest {Get-TabExpansion, Start-TabExpansion}
  Pscx.TerminalServices    Manifest {Stop-TerminalSession, Disconnect-TerminalSession, Get-TerminalSession}
  Pscx.Text+Aliases        Script   {lorem, ConvertFrom-Base64, ConvertTo-UnixLineEnding, Get-LoremIpsum...}
    Pscx.Text              Manifest {ConvertFrom-Base64, ConvertTo-UnixLineEnding, Get-LoremIpsum, ConvertTo-Base64...}
  Pscx.Vhd                 Script   {Mount-VHD, Dismount-VHD}
  Pscx.Xml+Aliases         Script   {cvxml, fxml, slxml, Convert-Xml...}
    Pscx.Xml               Manifest {Convert-Xml, Test-Xml, Format-Xml, Select-Xml}
Oct 2, 2009 at 3:27 AM

I wonder if we should put Get-Random, Select-Xml and Start-Process into a module named legacy or deprecated or something to that effect?  These conflict with the built-in cmdlets of the same name.  I also think we should nuke the TabExpansion code.  It has fallen into abeyance, crashes on x64 and is turned off in PSCX 1.2.  Even if it worked, is it significantly better than the built-in tab expansion or PowerTab?  Also, where are the FileSystem and Archive modules?

Oct 2, 2009 at 3:31 AM

Sounds good - making the providers and their default drives on-demand is probably a good thing. I like the structure you've got there - so how is that physically? Are we going to drop a .psd1/.psm1 pair in each of the root-level folders in our pscxsnapin project, or are we going to keep all of our module scripts in a single folder? I'm thinking if we keep the sub-modules in the relevant root of each folder, maybe it might be easier to maintain over time...

I don't see the archiving cmdlets anywhere?

Oct 2, 2009 at 3:44 AM

It's not complete yet, there are many commands and nearly all scripts missing. Obsolete stuff should get its own opt-in module.

Regarding tab expansion, I'd rather fix it. IMbiasedO it's much better than the built-in or PowerTab.

Physically, there's a \Modules folder containing all the .psd1 and .psm1 files. Some sub-modules have a subfolder with type and format data (e.g. \Modules\SIUnits\type.ps1xml).

I would rather not mix these "configuration" files with the C# source files, altough the structure is very similar. Also the script modules and manifests should be all in one directory to allow easy loading with $Env:PSModulePath.

Oct 2, 2009 at 3:50 AM

PS. is there any workitem for the tab expansion crashes on 64-bit OS? 

Oct 2, 2009 at 4:01 AM
I think that any cmdlets that conflict should definitely go in separate modules.  I'd argue you should only "deprecate" them if they're not better than the ones in PS2 ... I'm not 100% sure of the feature-set of all three of those, so I can't say whether I think they're deprecatable -- if you've got cmdlets which you feel are clearly better than the defaults, you should probably consider "deprecated" versus "alternate" or something.

I gotta admit I always liked the idea of a compiled tabexpansion, but honestly -- as PowerTab illustrates -- it's a really complicated thing with boatloads of possible ways it could be tweaked. I haven't used the PSCX one in a while, but PowerTab hasn't been working for me either, so I'd like to see at least one of them fixed for 2.0 :-(

I think it would be great if the providers were separate, but from the sounds of it they're always going to be loaded, right?  I'm not sure it's really a good idea to load the provider and not load its formatting information.

Oh, and one other thought: just how much are people going to have to type to load these now?

Oct 2, 2009 at 4:18 AM
Edited Oct 2, 2009 at 4:19 AM
Oh, and one other thought: just how much are people going to have to type to load these now?

ipmo pscx

I think it would be great if the providers were separate, but from the sounds of it they're always going to be loaded, right?  I'm not sure it's really a good idea to load the provider and not load its formatting information.

Yeah, all providers seem to be loaded no matter what. However, if they wouldn't create any drives, you wouldn't really know they are loaded unless you called get-psprovider. You'd have to manually load some pscx submodule and then manually create a new PSDrive. Maybe it would be possible to detect that situation in the provider and issue a warning. Even so, loading a custom set of submodules should be rather advanced feature, and I wouldn't consider this deficiency to be a deal-breaker. Users should quickly realize they failed to load something because the default drives would be missing.