Use the KISS Principle for Your PowerShell Script

Use the KISS Principle for Your PowerShell Script

  • Comments 5
  • Likes

Summary: Microsoft Windows PowerShell MVP, Sean Kearney, teaches how to use the KISS principle for your Windows PowerShell script.

Weekend Scripter

Microsoft Scripting Guy, Ed Wilson, here. Sean Kearney graces us with his words of wisdom today as our guest blogger.

Photo of Sean Kearney

Sean Kearney is an infrastructure support analyst and Microsoft MVP in Window PowerShell. He is absolutely passionate about automation technologies—especially Windows PowerShell. If you say, “PowerShell,” he may just break into song. Sean considers himself “just a tech at heart,” but he can often be found dabbling with most Microsoft technologies at a moment’s notice. We have also been advised to keep him at arm’s length from any open Starbucks in Seattle.

Sean's contact information:
Twitter: EnergizedTech
Blog: Energized About Technology
Website: PowerShell: Releasing the Power of Shell to You
MVP profile
LinkedIn profile

After looking at a lot of submissions in the 2011 Scripting Games, I had one thing I thought I’d throw out there: the KISS principle.

No, I do not mean that I am going to break out into parody of “I was made for lovin’ you, baby” by a certain rock group from the ‘70s. I mean simplicity.

I do not mean necessarily “simplicity of the script.” That can be interpreted in a myriad of ways. I mean simplicity of your thought process. Sometimes we need to think simply for the solution.

Yes, there are absolutely some better-practiced ways, more efficient ways to write the code—flows of binary that would make Bill Gates himself jump out of his chair and say, “Whoa! DUDE!”

But my background is as an IT professional. The amount of time that we may have to code a Windows PowerShell script (or any other solution for that matter) is INVERSELY proportionate to the amount of time our customers let us have free time to ourselves. We all know that sometimes that amount of time is about enough to sneeze, and maybe wipe your nose if you are lucky.

So when I write the script, it is a “NOW” solution.

For example, in the 2011 Scripting Games, I had to write a solution to quickly parse the Windows Update log for FATAL or ERROR. I received critique because, “It wasn’t necessarily the best solution.”

This is true. When presented with the task, I went about it with the thought process, “The boss has a computer, I’ve got 60 minutes to find the answer, I don’t have the Administrators Guide for Windows PowerShell handy, and (like the typical ITPro) I probably didn’t even have breakfast that morning.

My premise in script writing is “keep it simple.” I put my flow into the script so I can look at it immediately and understand "what I was thinking” when I go back to that script later.

When looking at the scripts during the games, I saw some absolute works of art that were applications unto themselves, but I kept thinking, “Simpler, simpler.”

I like a script that somebody can look at and immediately understand what I was thinking. I like “simpler” whenever possible.

Sometimes simple does involve breaking it into a function, but it depends on the purpose of the script. Whether it’s a one off solution or not, I tend to think out loud and type away. For example, in Beginner Event 6, the task was to get lines to match certain content, so my mindset was, “GET the CONTENT of the WindowsUpdate.log file first,” as shown here:

GET-CONTENT C:\Windows\WindowsUpdate.log

Then I was thinking to quickly examine the lines for a particular piece of content, as shown here:

GET-CONTENT C:\Windows\WindowsUpdate.log | WHERE-OBJECT { $_ –like ‘*fatal*’ }

Is this the FASTEST approach? Is this the BEST approach? Probably not. But it’s a simpler approach. The code just works. It CAN be improved without question, and it should be revised—but looking at its flow, it makes simple sense. More importantly, I am done with the task. I can now quickly focus on the more pressing issues, like unlocking some user account in the Accounting division for the 32nd time this hour.

Sometimes I have no clue about what the best approach is. I may just be typing things in Windows PowerShell, similar to the first time I had to query Active Directory to find who hadn’t logged in recently. I had the Quest.ActiveRoles cmdlets installed at the time. I pulled up a quick list of users like so:

GET-QADUSER

And yes, B-O-Y, did it pull down a massive list—because I didn’t filter it. But piping it into Get-Member showed me that I could examine a property called CreationDate. I just wanted to see a list of users that had been created in the past 90 days. My thought process was as follows:

“GET me the list of USERS and store them away.”

“GET the date and store it away.”

“FOR Each user in the list, check the CreationDate against Today.”

“Show the Name on the Screen if they are LESS than 90 days old.”

This is what I wrote:

$LISTOFUSERS=GET-QADUSER

$TODAY=GET-DATE

FOREACH ( $PERSON in $LISTOFUSERS ) {

If (($TODAY - $PERSON.CreationDate) –lt 90) { WRITE-HOST $PERSON.Samaccount }

}

This is not necessarily the best approach, but it is the simplest approach (not in code, but in thought process). And that’s the point of Windows PowerShell. It is to try to come up with a simpler approach to getting things done. Whether you use a one-liner or even a simple foreach statement.  

Don’t forget. If it’s something you use on a regular basis, you can ALWAYS improve and revise it later. Your wheel may not be the BEST one your first time, but I am certain it (even if it is inefficient) will make YOU faster by making you more consistent.

…and this will make you look like a superhero.

Thank you, Sean, for this blog about practical scripting. You ARE a superhero—even if you do not wear tights and a cape.

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
  • I would  disagree here...

    I mean I like it simple, really. But to keep things simple it's good to know the tool you are working with. Knowing basic cmdlets (like get-content and where-object) is fine but using only basic cmdlets *prevents* you from having simple solution. If you learn PowerShell long enough you should know that there is cmdlet *designed* to Select-String, and use it. And if you do not know it - just Get-Command *string* or something along those lines.

    Also: if you work with AD long enough, you should always keep in mind, that your test AD with 10 users won't barf at you if you try to get all users at once and store them in array, but production with 1000s of users - probably won't (you will hit page limit and you will not get full list). And in PowerShell, especially with Quest stuff, you can risk a bet, that there is parameter for each cmdlet that will help you. How anything can be any simpler than:

    Get-QADUser -PasswordNotChangedFor 90

    Filter moved to left is always good thing to try. ;)

    So my suggestion: if you want to keep it simple, give a Get-Command, Get-Help and [TAB] a try, and if you think there is something that should help you get results you need, try it... I had no idea there is this parameter for Quest, I just typed Get-QAduser -Pass, pressed [Tab] few times and it was there waiting for me to grab it, used it, and leave all account that have password changed alone. ;)

  • Hello Sean,

    I like the easy, simple and readable approach, too!

    It is great that you can have things done in a couple of clearly written lines of Powershell code!

    But you know that I'm the error guy ( probably I should rename :-) and this spoils the easy flow of code and

    in fact a script may quickly become less obvious and readable, if you address error handling.

    Another thing that I found out to be cruel reality, is that you nearly never build a script for one special purpose.

    I hardly coded anything, that stayed a temporary solution and the trouble begins at least, if your coworker asks you

    if you can give this tiny little script, you just wrote for a special purpose, to him!

    A last point to mention is that I really would prefer to know my tools as far as I can get.

    And it is no failure to make the most of them even if others don't understand each facet of these tools.

    If I can provide a very elobarated solution that is stable, scalable and very efficient it may make sense to

    invest more time.

    But you are certainly right, that there are always a lot of opportunities where you are forced to solve something at once

    having no time to think of better appoaches. So just write down a working solution and don't care how long it takes to

    complete the tasks is a legal and often the only way to get things qickly done.

    The great thing about Powershell is that each approach could be implemented in it!

    Great!

    kind regards, Klaus

  • And to that end... we see the absolute strength of Windows Powershell.  You CAN take a "KISS" approach and get the job done easily (So new Admins can just get up and running) but on the SAME token you can take it and BUILD upon that solution for the long term.

    My point is actually "Simple" - If you're a new Admin, trying Powershell just don't think too hard on the problem initially.  You can find a short term solution that works right away and you can ALWAYS take upon that and build.

    Cheers all :)

    "the Energized Tech"

  • hi Microsoft Scripting Guy:

    i want ping a ip list,how to do that use System.Net.NetworkInformation.Ping.Sendasync() ?

    i write part of code:

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

    $ping = New-Object System.Net.NetworkInformation.Ping

    $pingReply = New-Object System.Net.NetworkInformation.PingCompletedEventArgs

    $ping.PingCompleted += [System.Net.NetworkInformation]::PingCompletedEventHandler($pingReply)

    $ping.Sendasync("192.168.1.1")

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

  • I'm not sure if the blogger is being deliberately provocative...but I'll bite.

    I agree and disagree :)

    I agree that a script that is easily understood is what we should go for, and that time spent on efficiency should be commensurate with the number of times the script is likely to be used.

    But after using powershell for some time I've found that I automatically think in terms of pipelines. They are what is special about powershell and I've found that thinking in terms of pipelines generally gets me a result quickly. Your example, with commands like IF and FOREACH, shows the sort of thinking used by a BASIC programmer (does anyone remember BASIC?); not a powershell scripter.

    Pipelines make us think in a particular way. They make us think about the result first, and then about what data sources might help you achieve that result, and the types of filters (e.g. where-object), operations (e.g. sort), and transformations (e.g. select-object) that will get you to the results. In fact they should be actively encouraged in powershell.

    Go pipelines!