All posts by Jeffery Hicks

PowerShell for the People: Making the shell work for you

021913_2047_WordTest1.png Once you have some basic PowerShell experience I think you will begin looking for all sorts of ways to use PowerShell. Although one of the biggest obstacles for many IT Pros is the thought of having to type everything. Certainly, PowerShell has a number of features to mitigate this, often misperceived, burden such as tab completion and aliases. It is the latter that I want to discuss today.

An alias is simply an short command name alternative. Instead of typing Get-Process you can type ps. Even I can’t screw that up. Using aliases at the command prompt is a great way to speed up your work and cut down on typos. While I wouldn’t type this in a script:

At a prompt, it is quick and I get the desired results. However, you can’t create an alias for a command and its parameters. For example, I love the -First and -Last parameters with Select-Object. But I can’t create an alias equivalent to Select-Object -last 10. What you can do however, is create your own wrapper around a command and put an alias to that. Here is a function I wrote for Select-Object -Last X.

You’ll notice that the last part of my code snippet is defining an alias called Last that references this function. But now I have something quick and easy to use at a PowerShell prompt.

You’ll have to figure out the best way to wrap the cmdlet. In this case, I am taking each piped in object and adding it to an array, only keeping the specified number of items. As each item is added, the other items are moved “up” in the array.

Be aware that there may be a trade-off between convenience and performance. This command using my alias and custom function:

took 237ms. Whereas the Select-Object approach:

Only took 49ms. But I bet you might be willing to accept that tradeoff to save some typing. Of course, if there is a Last command there should be a First command.

Performance-wise this is easier because all I have to do is count piped in objects and bail out once I reach the limit.

In this example I’m not only taking advantage of aliases, but also positional parameters and only having to type enough the of the parameter name so PowerShell knows what I want.

So there are ways to make PowerShell more keyboard friendly, although it might take a little work on your part. Next time we’ll look at another alternative.

Friday Fun: Read Me a Story

announcer A few days ago, someone on Twitter humorously lamented the fact that I expected them to actually read a blog post. After the laughter subsided I thought, well why does he have to? Perhaps I can make it easier for him. Plus I needed something fun for today. So I put together a PowerShell function I call Invoke-BlogReader which I think you’ll have fun playing with. It isn’t 100% perfect and as with most Friday Fun posts, serves more as an educational device than anything.

The function uses the .NET System.Speech class which seems to be a bit easier to use than legacy COM alternative. Here’s a snippet you can test.

So basically, all I have to do is get the contents of a blog article and pass the text to the voice object. That is a bit easier said than done which you’ll see as you look through this code.

The function uses the Invoke-WebRequest cmdlet to retrieve the content from the specified web page and I then parse the HTML looking for the content.

This is the trickiest part because different blogs and sites use different tags and classes. There is a getElementsbyClassName method, but that seems to be hit and miss for me, so I’ve opted for the slower but consistent process of using Where-Object.

Once I have the content, I could simply pass the text, but I realized I may not want to listen to the entire post. Especially for my own which often have script samples. Those aren’t very pleasant to listen to. So I realized I needed to parse the content into sentences. Regular expressions to the rescue.

Don’t ask me to explain the regex pattern. I “found” it and it works. That’s all that matters. $Sentences is an array of regex match objects. All I need to do is pass the value from each match to the voice object. The other benefit is that I can include a parameter to also display the text as it is being read.

That’s all there is to it! If you want to try out all of the options here’s a sample command:

Where this can get really fun is using another function, which I’m not sure I ever posted here, to get items from an RSS feed.

Putting it all together you can get the feed, pipe it to Out-Gridview, select one and have the blog read to you!

So now you can have your blog and listen to! There are probably a number of ways this could be enhanced. Or perhaps you want to take some of these concepts and techniques in another direction. If so, I hope you’ll let me know where you end up. Have a great weekend.

Tracking Your Day with PowerShell

timer Not too long ago, I received an email with a snippet of PowerShell code and a request for assistance. The code snippet used a little .NET code to retrieve the process for the currently active window. The goal was to have a PowerShell script run, keeping track of how long a given window was active. At the end of the day you would have a report of how you spent your day, at least based on active Window titles. As you might expect, faster than you can say “shiny ball”, I was all over this.

The code to get the active window was the easiest part. But I found I needed to take into account situations where the active process was for something non-interactive. I also found you get some odd artifacts when using Alt-Tab to cycle between open applications.

Once I had a collection of objects representing the different active windows, I realized it would be helpful to have a set of tools for measuring and analyzing the data so I wrote a function for that. The end result is a PowerShell module I call MyMonitor.

The module includes a custom format file and the .psm1 file adds some custom type definitions. The main command is Get-WindowTime. This command will monitor your windows for either a specified number of minutes, until a specific datetime, or if a specific process is detected. For tracking over longer periods of time use the -AsJob parameter.

You should end up with data that looks like this:

You can then measure the data.

Or see how much time you spent on Facebook.

This is from a small sample.

My module also includes an about topic, which I’ll post here

I hope you’ll try it out and let me know what you think. Be sure to read help and examples for all of the commands.

Download the MyMonitor zip file and extract to your modules folder.

Update: this will not track Windows 8 apps like Weather or Foo & Drink.