Category Archives: Scripting

Test 64-Bit Operating System

One of the great features of PowerShell is how much you can get from a relatively simple one line command. For example. you might want to test if a computer is running a 64-bit operating system. You can find out with a command as simple as this.

If you are running PowerShell 3 you could substitute Get-CimInstance. One thing to be aware of with this particular class is that the OSArchitecture property isn’t valid on older operating systems like Windows Server 2003. You’ll get an exception.

osarchitecture-fail

In this case I modified the WMI query to only return the OSArchitecture property, which doesn’t exist. Otherwise I would just get false which might not be entirely true. Of course, I always get carried away so before I knew it I had turned this one line command into a function.

The function takes a computername and optionally a PSCredential. You can use a saved PSCredential object or specify the name and you will be prompted.

Test-Is64Bit-01
The other design element is that if there is an exception caught I have a Switch statement to checks the message and writes a custom warning.
Test-Is64Bit-02

There’s no reason you can’t use the one-liner. But if you want to add a bit more robustness and create a re-usable tool, it doesn’t take much to turn it into a simple function.

Scrub Up PowerShell Content

scrubbrush It is probably a safe bet to say that IT Pros store a lot of information in simple text files. There’s nothing with this. Notepad is ubiquitous and text files obviously easy to use. I bet you have text files of computer names, user names, service names, directories and probably a few that are unique to your company. Getting data out of these text files is very easy in PowerShell using Get-Content.

The potential problem is that the text file may not be perfectly formatted. Your text file might have blank lines. Or your computername may have a trailing white space. These things can complicate using the text file in a PowerShell pipelined expression. One approach is to filter the content using Where-Object and simply look for the existing of something.

This works fine in filtering out blank lines. But won’t fail if you have a line where someone inserted a tab or hit the space bar a few times. So let’s take this a bit further and use a regular expression to filter out anything that doesn’t have a non-whitespace character.

This should get rid of any lines that are nothing but tabs or spaces. Of course, there is still the issue of leading or trailing spaces. But we can handle that by using the string object’s Trim() method.

This is starting to get complicated. So I wrote a filtering function to scrub up content presumably from text files.

We don’t use the Filter keyword much anymore but it seemed appropriate because that is the only thing Scrub is doing. In fact, I intentionally did not use a traditional verb-noun name. Technically this an advanced function this is just a Process script block. I wrote it with the assumption that you would pipe strings from Get-Content.

Each processed string is filtered to get rid of blanks and spaces. Then each string is trimmed of leading and trailing spaces and finally written to the pipeline. Now I can run a command line this:

scrubexample1

In my initial versions this solved all of my potential problems with text files. But then I realize I had an opportunity to add one more scrubbing feature. Many cmdlets have parameters that take pipeline input by property name. But strings from text files lack a property name. So I added a parameter to my Scrub filter to add a property name.

Now I’m writing an object to the pipeline and can take advantage of pipeline binding.

scrubexample2

I don’t know about you, but this will come in very handy. I hope you’ll let me know what you think.

PowerShell Scripting Games 2013 Impressions

Now that the PowerShell Scripting Games for 2013 are well underway, I thought I’d share my thoughts and impressions on what I’ve seen. I’m very impressed with the number of entries and generally the quality is pretty good. But as a judge I see repeated items that bear comment. These comments are in no particular order of importance and in some cases are really a matter of personal preference.

If you are going to use Write-Host (and want to save puppies) to display informational or progress messages, please use one of the color parameters so that your message can be differentiated from your object output. Ideally for advanced events you should be using Write-Progress. Not sure we’ve had events that call for Write-Progress but keep it in mind.

I generally dislike entries that are clearly overwrought and over-thought. Sometimes the problem can be solved simply. Don’t feel you have to use every trick in the PowerShell play book in order to score points. I’m a big proponent of the right tool for the job. On a related note, if you can solve the challenge with a PowerShell one-liner, don’t feel you need to write it as a long single line command. Take advantage of PowerShell parsing. This is very hard to read:

I’d much rather see a one-liner formatted like this:

In full scripts, I’d like to see more use of #Requires -version X so that I can tell what features you might be using. Related to that, in advanced scripts if you are using a parameter attribute like Mandatory or ValueFromPipeline, v3 scripts should use them like this:

You don’t have to explicitly state that Mandatory is equal to True. Although in v2 you would need to do this:

Which brings me to another minor irk, an object that has a boolean value doesn’t need a comparison operator. The whole point of something like an IF statement is to evaluate if the expression in the parentheses is true or not. If the object is already a boolean, there’s no need.

I’m also not a big fan of creating custom objects with lots of Add-Member commands. I think this makes the code harder to read and doesn’t really buy you much. I think using a hashtable with New-Object is much easier to read and just as effective. Plus in v3 we can now have ordered hashtables and even use [pscustomobject].

Finally, be very careful of including formatting commands in your entries, unless the event specifically calls for it. This is especially true if you are writing a function. When you include formatting directives at the end of the function, it can’t be used anywhere else in a PowerShell expression.

Don’t get me wrong, there is a lot of good PowerShell which I’m happy to see:

  • Using Join-Path to build paths
  • Using Test-Path to validate
  • Plenty of internal comments
  • Using Test-Connection to verify computers are online
  • Meaningful variable names

So keep up the good work and on to the next event!

Getting Top Level Folder Report in PowerShell

One of the sessions I presented recently at TechDays San Francisco was on file share management with PowerShell. One of the scripts I demonstrated was for a function to get information for top level folders. This is the type of thing that could be handy to run say against the root of your shared users folder. Or the root of a group share where each subfolder is a share that belongs to a different group. My function takes advantage of a new feature for Get-ChildItem that makes it much easier to retrieve only file or directories. Here’s my Get-FolderSize function.

The function defaults to the local path and gets a collection of all of the top level folders, that is, those found directly in the root. The function then takes the collection of folders and pipes them to ForEach-Object. Most of the time we only use the Process scriptblock with ForEach-Object, but I want to take advantage of the Begin and End blocks as well. In the Begin scriptblock I measure all of the files in the root of the parent path and create a custom object that shows the number of files and total size in bytes. I’m going to get this same information for each child folder as well.

The process scriptblock does just that for each top level folder. This version of my function uses Write-Progress to display progress and in the End script block I have code to complete the progress bar, although It works just fine without it.

Other techniques I’d like to point out are the use of splatting and error handling. You’ll notice that I’m using the common -ErrorVariable parameter. After exploring the different types of exceptions I decided I could easily display any errors and the paths In the Catch block. I’m using Write-Warning, but this could just as easily be written to a text file.

The function writes an object like this for every folder.

Here’s an example of complete output:

foldersizeBecause I’ve written objects to the pipeline, I could pipe this to Out-Gridview, export to a CSV file or create an HTML report.

This is just a taste of what you can accomplish with some basic PowerShell commands.

 

PowerShell Messagebox

messageboxRecently I posted an article explaining how to create a popup box in PowerShell using the Wscript.Shell COM object from our VBScript days. That was something I presented at the PowerShell Summit. Another option is a MessageBox, again like we used to use in VBScript. This works very much like the popup except the user has to click a button to dismiss the box. I can’t think of a compelling reason why you would choose one technique over the other if you need the user to click something. But I’ll let you make that call. Here’s the function, New-Messagebox.

Most of the function is a wrapper around this line:

Like the popup function, I wanted to make it easier to create a messagebox without having to remember the names for buttons and icons so I use validation sets with my parameters. This makes it much easier to create a command like this in your script:

In the version I presented at the PowerShell Summit, the function did not write anything to the pipeline unless you used -Passthru. After thinking about it more, I realized the whole reason you are likely to use a MessageBox is to capture an interaction so I flipped the parameter and now it is -NoPassthru. Now, when the user clicks a button, the text value of that button is automatically written to the pipeline. If you include -NoPassthru you’ll get nothing. Here’s an example:

messagebox2

Because the messagebox writes text to the pipeline, it is a little easier to use than the Popup technique where you have to decode an integer value. In any event, you now have some options.

If you find this useful, I hope you’ll let me know.

Why Doesn’t My Pipeline Work?

talkbubble I saw a little discussion thread on Twitter this morning which I felt needed a little more room to explain. Plus since we’re in ScriptingGames season beginners might like a few pointers. I always talk about PowerShell, objects and the pipeline. But sometimes what looks like a pipelined expression in the PowerShell ISE doesn’t behave the way you might expect.

Here’s an example.

If you run this, you’ll see numbers 1 to 5 written to the pipeline. But if you try something like this it will fail.

You’ll get an error about an empty pipe. In fact, in the PowerShell ISE you’ll get a red squiggle under the | indicating this is not going to work. That’s because PowerShell isn’t writing to pipeline at the end of the scriptblock, but rather within in. Another way to think about it is at the While operator is not a cmdlet so the only thing writing objects to the pipeline is whatever commands are within the While loop.

What you can do is something like this:

Here, I’m capturing the pipeline output from the scriptblock and saving it to a variable. Then I have objects I can use. Or if you wanted to be clever, you could use a subexpression.

This same behavior also applies to Do and the ForEach enumerator. The latter trips people up all the time.

You think you’ll get the output of ForEach saved to the file, but you’ll run into the empty pipeline again. You could use a variable and then pipe the variable to the file or use a subexpression. Even better, use a pipelined expression.

Here I’m using the cmdlet ForEach-Object, which unfortunately has an alias of ForEach which confuses PowerShell beginners. So don’t assume that just because you see a set of { } that you get pipelined output. Remember, cmdlets write objects to the pipeline, not operators.

PowerShell PopUp

popupAt the recent PowerShell Summit I presented a session on adding graphical elements to your script without the need for WinForms or WPF. One of the items I demonstrated is a graphical popup that can either require the user to click a button or automatically dismiss after a set time period. If this sounds familiar, yes, it is our old friend VBScript and the Popup method of the Wscript.Shell object. Because PowerShell can create and use COM objects, why not take advantage of this?

All it really takes is two lines. One line to create the Wscript.Shell COM object and one to invoke the Popup method.ย ย (Yes, I’m sure you could do this in one line, but that’s not the point.)

The Popup method needs parameters for the message, title, a timeout value, and an integer value that represents a combination of buttons and icons.

popup2The challenging part has always been trying to remember the integer values. So I wrote a quick function called New-Popup.

The function lets you use text descriptions for the buttons and icons. In PowerShell 3.0 you will also get tab completion for the possible values. This makes it easy to create a command like this:

The function writes the value of the clicked button to the pipeline. I expect this is something you are more apt to use in a script. Perhaps to display an error message or even to prompt the user for an action. Maybe you’d like to use it in your PowerShell 3.0 profile:

The popup will automatically dismiss after 5 seconds unless I click Yes or No. You should be able to copy the function text from the listing above by toggling to plain code, select all and copy.

I hope you’ll let me know where you use this.