Friday Fun: Improved PowerShell Napping

So I had some fun with my post last week on taking a nap with PowerShell. I got some great feedback on Twitter and a new comments on the blog. My initial effort was a relatively simple PowerShell script which certainly got the job done. But I there were a number of areas where I could expand and improve the script and they would be terrific teaching aids. So I did.

The function is defined in a script you can find in Github.

Let’s look at some of the changes I made. First off, I turned this into a function complete with comment based help. You’ll need to dot source the script file into your PowerShell session or profile script to make the command available.

I made just about every option a parameter and added a few parameter aliases as well. So even though I made the Minutes parameter positional so that you don’t need to use the parameter name, you could use –Nap or –Time. You’ll notice I also made the wakeup message a parameter.  Feel free to set your own default value. Otherwise, you can set a different message at different times.

I also realized that if you are napping, someone might still drop by your desk. So I included an option to display a progress bar using Write-Progress. This is a cmdlet that doesn’t get the love it should.

I defined an array of messages:

The messages will be used as the Status property for Write-Progress. I like using a hashtable of parameters to splat when using Write-Progress.

If I use the Progress bar, it is displayed using the seconds remaining.

And every 10 seconds I set the status to another randomly selected message. The result is something like this:

image

The last major change I made per a suggestion was to use the text to speech feature to have a Windows voice “say” the wake up message. I added a parameter for you to specify a voice name which in the US will most likely be David or Zira.  If you don’t know the names, you can specify a bogus value like ‘foo’ and the function will display the available names. This works because I added a validation script to the Voice parameter.

This is probably a bit more involved than most validation scripts.  The main takeaway is that if you use a validation script it has to return either True or False, or throw an exception as I’m doing here. But it works.

image

By adding a voice option I decided the function could either display the message using Write-Host or speak it. The chime happens in either event.

What this meant was that I had to differentiate the parameters which I did with parameter sets.  I specified the default in the cmdletbinding attribute.

Then I needed to specify a parameter set name for each parameter.  If you don’t specify parameter set name, then the parameter will belong to all sets.  Or you can do as I did and be explicit. If you do it properly it should be reflected in the help.

image

You can see that there are 2 ways to use this command. I’ll let you grab a copy and try out the new additions.

Certainly this isn’t a production oriented script but I hope it serves up some interesting examples of different scripting techniques and cmdlets.

As always, comments sincerely welcomed.

Enjoy!

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.

Friday Fun: Messagebox Writer

yellowsub For today’s fun I’m revisiting a topic I’m sure I’ve written about in the past and that is creating a graphical message box in PowerShell. There are a few ways you can do this from using the Visual Basic classes, the old standard WScript.Shell object from VBScript or using WinForms. They all basically work the same way and you probably can’t tell from the message box what was used to create it. So I took my version of New-MessageBox which uses the Visual Basic interaction class and updated it a bit.

Here’s the new function.

This version has been tweaked to include better parameter validation. I also modified it so that the parameters accept pipeline input by property name. I think the function is pretty well documented so I won’t spend much time discussing it. You can try it out for yourself. Be sure to test with bad parameter values so you can see how validation works.

If you had grabbed an older version of this function, there is one breaking change. In the past I think I had the function always write the clicked button value to the pipeline. Now the function doesn’t write anything to the pipeline unless you use -Passthru. When you run a command like this:

You will get this:

MsgBoxYesNo

Nothing will be written to the pipeline because I didn’t use -Passthru. Now for the extra-fun part. If you read through the code listing, you may have seen references to a speech assembly. I figured, why not include an option to have the message spoken aloud? So I’m using the System.Speech.Synthesis.SpeechSynthesizer class to speak the text in the message box. Use the -Voice parameter to turn this on. PowerShell will use the default voice for your system. But wait, there’s more! I also included a second parameter, VoiceGender, so that you can specify if you want a Male or Female voice. On later client operating systems I believe you get one of each automatically.

Click here to view the video full size or right-click and save the video clip.

Here’s the sample script I ran.

Enjoy!