A Module to Create Modules and Advanced Functions

A Module to Create Modules and Advanced Functions

Rate This
  • Comments 9

[1/3/09 Update - the original link to the attachment containing this code was broken but is now fixed.  Sorry. jps]

It is hard to overstate how important Modules and Advanced Functions are.   If you are a PowerShell user - you need to take the time to learn these new mechanisms and use them as your first choice in implementing new functions.  The reason for this is that these mechanisms are critical technologies to support SHARING. 

Advanced Functions provide help, parameter tab-completion, and cmdlet semantics that make it easy for other people to use your functions.  Who wants to have to keep going back to read the source code to figure out what a function does - you want help.  Who wants to guess at the parameters - you want tab completion.  Who wants a functions that can have unintended consequences - you want -WHATIF -CONFIRM and -VERBOSE.

Modules make it easy to package functions and use them in ways that they don't collide with each other.  BTW - I'm not sure whether we've been clear on this point or not but Modules provide an alternate mechanism to do what PSSNAPINs did.  In fact MODULES work with both PSSCRIPT and DLLs.  The benefit of Modules over snapins is that they can be xcopy deployed.

The only downside of using Modules and Advanced Functions is that they both require extra work when you start writing code.  That is why I wrote the Module Module (that is probably a horrible name but I'm going with it for now).  This module makes it easy to create Modules and Advanced Functions AND it is a reasonable example of both.

PS> Import-Module Module
PS> Get-Command -Module Module

CommandType     Name                          Definition
-----------     ----                          ----------
Function        New-GUID                      ...
Function        New-ModuleTemplate            ...
Function        New-PSScript                  ...

New-PSScript requires a VERB and NOUN and optionally takes a number of other parameters and generates the body of a script or a function including help comments.  You can then redirect that output into a file.  Here is an example:

PS> New-PSScript -Verb Get -Noun MyProcess -Parameter ID `
>> -Synopsis "This is My Version of GetProcess"
>>
<#
.Synopsis
    This is My Version of GetProcess
.Description
    QQDescription

.Parameter ID
.Example
    Get-MyProcess
.ReturnValue
    QQReturnValue
.Link
    QQLink
.Notes
NAME:      Get-MyProcess
AUTHOR:    RugratsVista\jsnover
LASTEDIT:  01/02/2009 10:10:24
#Requires -Version 2.0
#>

[CmdletBinding(
    SupportsShouldProcess=$False,
    SupportsTransactions=$False,
    ConfirmImpact="None",
    DefaultParameterSetName="")]
param(
[Parameter(Position=0)]
$ID
)

Begin
{
}#Begin

Process
{
    Throw "Not Yet Implemented"
}#Process

End
{
}#End

New-ModuleTemplate does something similar for Modules.  It requires a NAME and it generates a .PSD1 file describing the module and a .PSM1 file with a GET-NAME function.  The nice thing about this command is that it takes a switch –EDIT and if you specify it, it will open these files in Powershell_ISE so you can immediately start coding. 

Install the module by copying the files to a directory called MODULE in your module directory:

($Env:PSMODULEPATH -Split ";")[0]

If you haven’t already created your module directory, you can do this:

PS> New-Item –Type Containter –Force –path ($Env:PSMODULEPATH -Split ";")[0]

Now if you are like me, you don’t want to be typing that crap all the time so when you import-Module Module, the first thing it does is to create a PSDRIVE for you called MYMOD.

New-PsDrive -Scope Global -Name MyMod -PSProvider FileSystem -Root (($env:PSMODULEPATH -split ";")[0])

Give these a try and let me know what you think.  They all have HELP and the HELP has examples so party on.

Again – it is hard to overstate how important it is to begin using Modules and Advanced Functions.  In particular, you should start using them today and let us know if there are any bugs or problems or opportunities for improvement.  We have a relatively short window to make any changes for V2 so start today.

Enjoy!

Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Attachment: module.zip
Leave a Comment
  • Please add 3 and 1 and type the answer here:
  • Post
  • Nice Post - I love the concept! I will look to play with this!

    One point: In the penultimate setup command above, you typed:

    PS> New-Item –Type Containter –Force –path ($Env:PSMODULEPATH -Split ";")[0]

    On my system, with CTP3, this caused an error:

    C:\> New-Item -Type Containter -Force -path ($Env:PSMODULEPATH -Split ";")[0]

    w-Item : The type is not a known type for the file system. Only "file" and "directory" can be specified.

    line:1 char:9

    New-Item <<<<  -Type Containter -Force -path ($Env:PSMODULEPATH -Split ";")[0]

     + CategoryInfo          : InvalidArgument: (:) [New-Item], PSArgumentException

     + FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.NewItemCommand

    A modified version did, however work:

    C:\> New-Item -Type directory -Force -path ($Env:PSMODULEPATH -Split ";")[0]

     Directory: C:\Users\tfl\Documents\WindowsPowerShell

    de                LastWriteTime     Length Name

    --                -------------     ------ ----

    ---          1/2/2009   6:28 PM            Modules

  • Shouldn't that be Container instead of Containter ?

    At the moment I can't seem to download the attachment.

  • There are some bugs with the help for the advanced functions.  I have filed one dealing with the parameter attributes not coming through correctly in the help if you have multiple parameter sets.  I very well may just be doing this wrong, but please check out the bug on connect, so maybe you can set me straight.

    Thanks!

  • This is a great idea and I would love the source code.

    But the link to Module.zip appears to be broken?

    Any suggestions would be appreciated.

  • I recommend you actually put #requires outside of the help comment block; otherwise, (at least as of CTP3) it will show up under "NOTES" (in the example above) when you do get-help on the function.

  • I think it is a common practice. First you create a sub module which implements all the necessary hooks for other modules to work nicely with your module. You solve it "in house" first, and when you think the code is perfect then you try to make a common goal with other module authors you try to work with..The module works with 3 other cont rib modules (and there are some patches for other module integrations in the issue queue). The code works nicely, but I would not push the code to other module maintainers yet..

  • I am trying to build a cmdlet which is to when system boots up number lock turns on by default.

    Can you give me some hits?

    Thank you so much!

    Cheers

    Jeff

  • Nice one.

  • Looks like there is a defect in the code. I fixed it on line 222 of the PSM1. Would you be able to correct the source?

Page 1 of 1 (9 items)