Summary: Microsoft Windows PowerShell MVP, Sean Kearney, begins a series of guest blogs that detail how to build your own cmdlet.
Microsoft Scripting Guy, Ed Wilson, is here. We have a special week in store for you. 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 1 of a nine-part series about building your own Windows PowerShell cmdlet. Read the entire series as it unfolds.
Here’s Sean…
You’ve opened up the Blue Console of wonder, the land of digital poetry we call Windows PowerShell. You’ve begun to write scripts to allow you perform your tasks with greater ease. Life feels so much better, but you still keep hitting a snag in the carpet.
One of the drawbacks to a script, just as we had with VBScript and our batch file days, is that you must specify the path to the script each time you execute it.
If you don’t like adding the path, you could dedicate a folder to all scripts in your system and add its location to the system path.
And now enter our hero: the advanced function
But Windows PowerShell opens an option that we didn’t actually have before. As of Windows PowerShell 2.0, we could create what is referred to as an “advanced function.” In many respects, an advanced function is much like a regular script except it stays loaded in memory, and it can mimic a binary cmdlet. There is one difference of course: an IT Professional can write an advanced function. It does not require the use of Visual Studio or higher-end tools. More importantly, it is not uncommon to modify an existing script into an advanced function.
Within these new cmdlets, you can even provide Help, examples for how to use them, and detailed instructions. It is not necessary to provide Help, but it is highly encouraged. Although it may not be the version of Microsoft Exchange, you should treat your advanced function like any other piece of software. Document it and provide as much Help as you can to enable your clients, even if your clients are your coworkers.
Like a script, your home-brew cmdlets can accept parameters and return objects. Plus, it can do something a little more impressive—it can sit in the pipeline and process the streams of data. For example, which of the following would you prefer?
Running something like this to process a list of new users for your company…
# Import List of new staff
$NewStaff=IMPORT-CSV C:\PowerShell\NewStaff.CSV
# Process and create accounts for new staff
FOREACH ($User in $NewStaff) {
C:\PowerShell\NewUserScript.Ps1 $User.First $User.Last
}
Or does this seem simpler and more appropriate?
IMPORT-CSV C:\PowerShell\Newstaff.csv | NEW-StaffMember –first $_.First –lastname $_.Last
Of course, both examples work fine. However, the second is more seamless appearing to users, and it almost steps into the concept of what a workflow would be.
GET A LIST OF NEW STAFF
CREATE ACCOUNTS FOR NEW USERS
I tend to prefer using cmdlets over scripts for my daily tasks. It feels like a quick sentence when I hear common phrases like “NEW USER for Accounting,” “DISABLE ACCOUNT for JOHN SMITH,” or “GET REPORT for SOX.”
Writing it as a script would work fine too, but I’ll be honest. I’m lazy. I don’t want to type path names, I don’t want to type extensions…really I don’t even want to type. Honestly, if it were cost effective and safe, I would like to hook myself into the system like Johnny Mnemonic and simply THINK the work that I want done.
But because I can’t do that (and because I shudder at what my brain would do if it imagined a blue screen of death), I go for Windows PowerShell and cmdlets. It’s simpler, more cost effective, and less likely of electrical overload from experimental brain interfaces purchased on eBay.
Let’s start with a script
So how do we start? Let’s take a very simple script. We will take this script and turn it into a function, and then into an advanced function. In this way, you should be able to take existing scripts and create your own cmdlets.
This script is going to create a text file with the name Logfile with the current date as part of the file name.
# GET the Current Date for our Logfile
$Today=GET-DATE
# Define folder to store logfiles within
$Folder=’C:\PowerShell’
# Name to assign to our Logfiles
$Preface=’Logfile’
# File extension to our Logfiles
$Extension=’.Log’
# 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 $FALSE }
ELSE
{
# Create logfile
NEW-ITEM –Type File -path $Logfilename -Force | OUT-NULL
# Return the Full path and filename if successful
RETURN $Logfilename
}
We’ll save this as a file name called newlogfile.ps1 in a folder called C:\PowerShell. This script will return one of two responses. If successful, it will produce a new blank log file along with the Boolean value $TRUE. If not, it will write to the Windows PowerShell error stream and return a Boolean $FALSE. It will always return the file and the folder location where it attempted to create it.
So we will run our current script in Windows PowerShell like this.
C:\PowerShell\newlogfile.ps1
This will give us either a success like so:
Or a failure (cue the sad trombone sound—or quickly go to Play Sad Trombone…”wah wah wahhhh…”) such as this:
~Sean
That is all for today. Thank you, Sean, for sharing. This is going to be a way cool Windows PowerShell series. Join us tomorrow when Sean will present Part 2. I can’t wait.
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