Tag Archives: Scripting

Friday Fun: Another Christmas Prompt

christmastree In last week’s Friday Fun post, I shared with you a PowerShell prompt that would display a festive Christmas countdown clock. This week I have another holiday related prompt function. This one is pretty straight forward and is not that much different from the default PowerShell prompt function.

I included some logic so that my customization only happens during the month of December and before Christmas. The prompt changes the background color of your console between DarkRed and DarkGreen. The first time you run it, the prompt will randomly select a color. You might want to run Clear-Host, or CLS after loading the prompt.

After that the background color will toggle leaving you with an effect like this:

christmasprompt2014-redgreen

It is interesting to see how different commands write to the console. You could even combine both of my prompts if you are in an especially festive mood.

christmasprompt2014-everything

There’s probably no practical value in this other than having some fun and maybe understanding some PowerShell scripting concepts. Hope your holiday shopping is going well. Have a great weekend.

Friday Fun: I’m with the band.

black-guitarI like to have fun with PowerShell, as is hopefully evident with this Friday Fun serious, and today that is especially true. Perhaps you need a quick break from the end of the week grind. Or maybe you want to learn something new about PowerShell. Hopefully today’s fun will meet both requirements. Today’s fun will include XML, scope and Switch. Let’s rock.

If you haven’t figured it out, rock ‘n roll is the theme for today. I have put together a little rock and roll quiz. In many rock bands there’s at least one member is well known. If someone says “Axl Rose” you most likely will know Guns n’ Roses. But would you recognize the other members of the band? I created an XML document with a number of well known rock bands. Because band members change, I tried to use the line ups from the bands peak years. If you want to play you will need to download BandData.xml. Save as an XML file to same directory as the script, which I’ll show you in a moment. Try not to peek too much at the contents. This is the structure.

My quiz is a PowerShell script that processes the data in the XML document. It will display a list of band members, without the recognizable lead and multiple choice of possible bands. After answering the questions you will be judged, I mean graded.

Let’s look at a few key points of the script.

First, I need to load the XML document.

The [XML] type accelerator will create an XML document. When you have an XML document in PowerShell, each node can be treated like a property so it is very easy to navigate or get values, like a list of all the band names.

The script then selects a random number of band entries from the XML document. These will be the basis of the quiz. For each item I create a list of band choices and band members that will be displayed. You’ll also noticed that I initialize some counters with the $script prefix.

Here’s why. I am using a scriptblock, defined as $promptblock, to display each question and keep track of correct answers. The scriptblock runs in a new scope, or container. That means when it tries to do something with a variable like $Q it first looks in the current scope for that item. If it finds it, it uses it. Otherwise PowerShell searches up the scope hierarchy to the parent scope looking for the item. But here’s what trips people up. If you are only reading, like I am, for things like the $bandhash object, PowerShell will happily find it in the parent scope and display it. But when I try to modify a variable like $Q or $i it can only modify it in the current scope. But I need to use those variables outside of the scriptblock scope, so I preface the variable with $Script: to indicate the scope level for those variables. The general rule is to not reference out-of-scope variables, but since I’m using $script: I’m telling PowerShell I know what I’m doing.

After running through all the questions, the script can calculate how many correct answers you had and present a score card. I decided to use a Switch statement to assist.

Normally in a Switch you would use a simple value. But you can also use PowerShell expressions. In my Switch statement, if the value of $Correct is >= 90, then I assign a certain value to $quip. When using expressions, use $_. Remember that Switch will process every matching expression and since I don’t want that, I’m using the Break keyword so PowerShell knows not to keep checking the other possibilities.

When you run the quiz, you will get an item like this:
bandquiz-1

The display is from the prompt scriptblock. If you need a little help, enter 0 which re-displays the question this time with the (hopefully) more recognizable lead.

bandquiz-2

And the final snarky commentary on your rock knowledge.
bandquiz-3

Because I am of a certain age, the contents of my band data xml file might be slightly skewed. If you were born after 1985 you might have some problems.

I think XML files scare some IT Pros but they really aren’t that difficult to work with once you understand some basics. In fact, I’ll be coming back to my band xml file in future posts. In the mean time, party on and let me know if you have any questions about my quiz script.

Scary PowerShell

In honor of today’s festivities, at least in the United States, I thought we’d look at some scary PowerShell. I have seen a lot of scary things in blog posts, tweets and forum discussions. Often these scary things are from people just getting started with PowerShell who simply haven’t learned enough yet to know better. Although I have seen some of these things from people who appear to be a bit more experienced. I find these things scary because I think they are “bad” examples of how to use PowerShell. Often these examples will work and provide the desired result, but the journey is through a terrifying forest. Please note that PowerShell style is subjective but I think many of the core concepts I want to show you are sound.

First, here is a chunk of scary PowerShell code. This is something I wrote based on a number of “bad” techniques I’ve encountered.

This code will create a CSV file with files in C:\Work that are over a certain size and modified after January 1, 2014. When I see code like this I am pretty confident the author is coming from a VBScript background. To me, I see a lot of energy working with text. I’ll come back to that point in a moment.

First, filtering is a bit ugly. Unless you have a specific byte value in mind, use shortcuts like 1MB which is easier to understand than 104876. You can also combine filters into one.

I cringe when I see people trying to concatenate values in PowerShell. In this case it simply isn’t needed. But for the sake of learning, if you really needed to build a string, take advantage of variable expansion. Here I will need to use a sub-expression.

But in the example of bad code ,instead of manually creating a CSV file, PowerShell can do that for you with Export-CSV.  In the code sample, the header is different than the property names, but that’s OK. We can use a hashtable with Select-Object and create something new.

The original code used text parsing to get the file extension. But if you pipe a file object to Get-Member, you would discover there is a property called Extension. When building scripts, pipe objects to Get-Member or Select-Object with all properties to discover what you have to work with. The original code is written with the assumption that the CSV file will be used outside of PowerShell. If that is the case, then export it without type information. But if you think you will import the data back into PowerShell, include the type information because it will help PowerShell reconstruct the objects. You would learn all of this by looking at help and examples for Export-CSV.

The example above is technically a one-line command. But it doesn’t have to be. It might make more sense to break things up into discrete steps.

This code is sort of a compromise and isn’t too difficult to follow, even if you are new to PowerShell. This would give you the same result.

Sometimes using the ForEach enumerator is faster than using ForEach-Object in a pipeline. You have to test with Measure-Command. If you are running PowerShell v4, you can take advantage of the new Where() method which can dramatically improve performance.

By now I hope you can see how this code is taking advantage of cmdlets and the pipeline. For example, Export-CSV has a –NoClobber parameter which prevents you from overwriting an existing file. You can’t do that with legacy redirection operators like > and >> without additional commands.

The final step with my scary code, which now isn’t quite so scary I hope, is to turn this into something re-usable. If you put the above into a script as-is, you would have to edit the file every time you wanted to check a different folder or export to a different file. This is where we can turn it from a pumpkin into a fantastic carriage, that won’t revert at midnight.

This function gives me a flexible tool. All I need to do is specify a path, although it defaults to the current directory, and some sort of filtering script block. The default is to display everything. Now I can run a command \ like this:

You’ll notice that my function doesn’t export anything to a CSV file. Of course not. The function’s only purpose is to get files and display a subset of properties. Because the function writes to the pipeline I can do whatever I need. Perhaps today I need to export to a CSV file but tomorrow I want to create formatted table saved to a text file.

I hope PowerShell in general doesn’t frighten you. As the saying goes, we fear that which we don’t understand. But once you understand some basic PowerShell principals and concepts I think you’ll find it not quite as terrifying.

What scary PowerShell have you come across