Build Your Own PowerShell Cmdlet: Part 3 of 9

Build Your Own PowerShell Cmdlet: Part 3 of 9

  • Comments 8
  • Likes

Summary: Microsoft Windows PowerShell MVP, Sean Kearney, continues a series of guest blogs that detail how to build your own cmdlet.

Microsoft Scripting Guy, Ed Wilson, is here. Guest blogger and Windows PowerShell MVP, Sean Kearney, has written a series about building cmdlets. For more about Sean, see his previous guest blog posts.

Note This is Part 3 of a nine-part series about building your own Windows PowerShell cmdlet. Read the entire series as it unfolds.

Here’s Sean…

We need to do a few minor things. First, we preface the entire script block from beginning to end as a function. But there are rules for becoming a real cmdlet. Just ask that Pinocchio character. The biggest rule is formatting the name. It must follow a Verb-Noun format. The noun should be singular. The third and most important rule that you shalt follow (less the Lords of Monad come crashing through your door), is to use one of the approved verbs in Windows PowerShell.

Approved verbs?       

Yes, approved verbs. Remember one of the biggest strengths in Windows PowerShell is the consistency of how various Windows PowerShell systems work. There is actually an approved list of verbs for the Verb-Noun pairing.

Would it surprise you to find that the list is built-in to Windows PowerShell? Just run the cmdlet Get-Verb. This will give you an output similar to the one shown here.

Image of command output

How do you choose an appropriate verb? Think of what you’re doing and apply a little common sense. Verbs are broken up into individual groups like Common, Data, Lifecycle, Diagnostic, Communications, Security, Other, and SwissCheese.

OK, fair enough. There is no SwissCheese group. I made that one up to see if you were reading. But when you want to write a cmdlet, think about what you are trying to do, and find a verb that seems to make sense.

In our case, we are adding a log file to our file system. Let’s see if there is a verb called Add.

Get-Verb Add

Running this cmdlet confirms that Add is a valid verb in Windows PowerShell, and it is a member of the Common group. This suggests that it’s pretty flexible for usage.

So remember the rule: it has to follow a verb-noun combination for it to be a real cmdlet. Here’s the tricky part. “Noun” is open to interpretation. Although most of the verbs in Windows PowerShell will be found in the standard Webster’s Dictionary at your local library, odds are that ADObject or QADUser won’t be.

So think of a Windows PowerShell noun as something more of a thing that you’re referencing. The name of the thing may only be unique to your system. In our case, we are adding a log file, so we can use the name pairing of Add-LogFile.

So let’s convert our present script to an Advanced function called “ADD-LOGFILE.”

function global:ADD-LOGFILE{

PARAM(

[STRING]$Folder="C:\PowerShell",

[STRING]$Preface="Logfile",

[STRING]$Extension=".log"

)

 

# GET the Current Date for our Logfile

 

$Today=GET-DATE

 

# Extract the Date removing the “/”

 

$Date=$Today.toshortdatestring().Replace(“/”,””)

 

# Extract the Time removing the “:”

 

$Time=$Today.tostring(“HH:mm:ss”).Replace(“:”,”“)

 

# Build our Filename

 

$Logfilename=$Folder+"\"+$Preface+”-“+$Date+”-“+$Time+$Extension

 

# Test and ensure file does not already exist

 

IF (TEST-PATH -path $Logfilename)

 

{ WRITE-ERROR –message “Error: $Logfilename exists.” –category ‘WriteError’

 

# If file exists, return a status of Boolean $False for Unsuccessful

 

RETURN $Logfilename,$FALSE }

 

ELSE

 

{

 

# Create logfile

 

NEW-ITEM –Type File -path $Logfilename -Force | OUT-NULL

 

# Return the Full path and filename if successful

 

RETURN $Logfilename,$TRUE

 

}

}

Let’s save this as a new Windows PowerShell script and call it C:\PowerShell\addlogfunction.ps1.

When we execute this script, it will appear to do nothing.

Image of command output

Before you start to go for that sad trombone link, your script DID work.

What you just did was define a global function named Add-LogFile. You then loaded it into the global scope within Windows PowerShell. This means that in your current session, the function has been defined and placed outside of the confines of the script, and it will be accessible by your current Windows PowerShell session after the script terminates.

To test your function, just key in:

ADD-LOGFILE

Image of command output

You can even run Get-Help on it—although the Help will be quite sparse at the moment.

Image of command output

~Sean

Thanks Sean! This really good stuff. Keep it coming.  It is great to have an honorary scripting guy in the house!

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • hi,

    thank's for sharing

    you can use this function to get Approved  comand (verb/noun)

    #############################################################

    #

    #  PS II> Test-CommandValidation -command get-process | fl

    #            VerbNounConvention : True

    #            ReservedKeyWords   : True

    #            VerbConvention     : True

    #

    #############################################################

    function Test-CommandValidation {

      param($Command)

      $keys = man key |

                Select-String "(\S+)(?=\s{5,}about_*)" |

                     select -expand Matches |

                           select -expand value

      $verbNounConvention = $verbconvention = $reservedkeywords = $false

      $verb,$noun = $Command.Split('-')

      if($noun) {

         $verbNounConvention = $true

         if( (get-verb $verb) ) { $verbconvention = $true }

         if($keys -contains $noun) { $reservedkeywords = $true }

      }

      else {

          $reservedkeywords = $verbconvention = $null

      }

       new-object PSObject -prop @{

          VerbNounConvention = $verbNounConvention

          VerbConvention = $verbconvention

          ReservedKeyWords = $reservedkeywords

       }

    }

  • @walid

    Nice job!  A way to test the whole Cmdlet for validity on the name :)

    I'd be almost tempted to step it up a level and put it a "Simple form".   Output "Green" and *PASS* if all is good or "Red" and show the spot for the error.  

    If you haven't already, post that into the TechNet Script Repository !

    Cheers

    Sean

  • I kind of expected Powershell to through a warning if I used function global:MYADD-LOGFILE; since the verb was unapproved.   but I guess its just convention?

  • @Sean Kearney

    ----> maybe like this ?

    function Test-CommandValidation {

     param($Command,[switch]$SimpleForm)

     $keys = man key |

               Select-String "(\S+)(?=\s{5,}about_*)" |

                    select -expand Matches |

                          select -expand value

     $verbNounConvention = $verbconvention = $reservedkeywords = $false

     $verb,$noun = $Command.Split('-')

     if($noun) {

        $verbNounConvention = $true

        if( (get-verb $verb) ) { $verbconvention = $true }

        if($keys -contains $noun) { $reservedkeywords = $true }

     }

     else {

         $reservedkeywords = $verbconvention = $null

     }

      $objPS=new-object PSObject -prop @{

         VerbNounConvention = $verbNounConvention

         VerbConvention = $verbconvention

         ReservedKeyWords = $reservedkeywords

      }

     if($SimpleForm) {

         switch($objPS) {

           {!$_.ReservedKeyWords -and $_.VerbConvention -and $_.VerbNounConvention}

             {Write-Host "PASS !!" -ForegroundColor green}

           {!$_.VerbConvention -and !$_.VerbConvention -and !$_.VerbNounConvention}

             {Write-Host "FAIL !!" -ForegroundColor red}

           default

            { Write-Host "MAYBE !!" -ForegroundColor DarkYellow }

         }

      } else {

        $objPS

     }

    }

  • When i do get-help Add-logfile returns the following, but not that detail as shown in the blog. Did i miss anything?

    Add-Logfile [[-Folder] <String>] [[-Preface] <String>] [[-Extension] <String>]

    Also the function is discoverable using tab expansion but its not when using get-help. Any way to do that?

  • @Sean - I sort of feel "New" would fit better here than Add... ;)

    @PoSHV - Sean is working on v3, you are probably on v2. V3 has many improvements in help area, this autogenerated help for functions that have no help at all being one of them. :)

  • Thanks Bartek. Yes, I am on V2. Will upgrade to V3.

  • For more detail about approved verbs, including when to use them, what pairs up with what etc. the MSDN page is very useful: msdn.microsoft.com/.../ms714428(VS.85).aspx