Wednesday, October 2, 2013

Everyday Powershell - Part 2 - The BOFH Speaks!

This is the next part in an ongoing series about Powershell. You may have heard about how awesome Powershell is but have struggled to find ways to make it useful in your day to day work. That's what this series is going to address. It'll provide scripts and knowledge to address practical everyday problems!

This script is a bit of fun that we can also use for learning! The everyday problem we're addressing here is the lack of funny in our days. I know you'll also be able to reuse the functions in the script for actual productive work but that shouldn't get in the way of the funny!

First step Fire up the Powershell ISE and paste this in, turn up your speakers, run the script and enjoy the funnies.
#requires -version 2
function Say-Text
{
    param ([Parameter(Mandatory=$true, ValueFromPipeline=$true)] [string] $Text)
    [Reflection.Assembly]::LoadWithPartialName('System.Speech'| Out-Null
    $object = New-Object System.Speech.Synthesis.SpeechSynthesizer
    $object.Speak($Text)
}

function download-file
{
    param ([string]$path, [string]$local)
    $client = new-object system.net.WebClient
    $client.Headers.Add("user-agent", "PowerShell")
    $client.downloadfile($path, $local)
}

$path = "http://www.cs.wisc.edu/~ballard/bofh/excuses"
$local = "c:\temp\temp.html"

download-file $path $local

$excuse = Get-Content $local | get-random
say-text "Today's excuse is... $excuse
"

Then save it as a .ps1 file somewhere sensible and look over Part 1 of this series for the low down on how to schedule this script to run on a daily basis!

Imagine it! You can have your Computer read out a BOFH excuse every day! This... THIS, is why I love Powershell.

Read on for a line by line breakdown of what is actually going on in the script!

Part 1
function Say-Text is actually a cool way to demonstrate functions and have a bit of fun with .net objects.

param ([Parameter(Mandatory=$true, ValueFromPipeline=$true)] [string] $TextEssentially this is just setting up the parameters that can passed to the function. In this case we're just pulling in a string called $text it's mandatory and can be passed from the pipeline.

[Reflection.Assembly]::LoadWithPartialName('System.Speech'| Out-Null This loads System.speech so we can use it. The pipe to out-null simply prevents dumping this kind of thing to your console...
True   v4.0.30319     C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Speech\v4.0_4.0.0.0__31bf3856ad364e35\System.Speech.dll    

$object = New-Object System.Speech.Synthesis.SpeechSynthesizer This creates a new .net object called $object.
NOTE - Something cool you can try once you've got an object like this is piping to get-member like this;
[Reflection.Assembly]::LoadWithPartialName('System.Speech')$object = New-Object System.Speech.Synthesis.SpeechSynthesizer$object | get-member 
You'll get this useful list of all the methods and properties of the object.
$object.Speak($TextNext up we simply called the object with the speak method and hand $text as the argument! There you have a talking PC!

Part 2
function download-file Next up is another function This one uses .net to pull down a file from a web server.

param ([string]$path, [string]$localSame as parameters in the previous function but this time there are 2! You separate them with commas. We're pulling in $path and $local take note of these we'll need them later!

$client = new-object system.net.WebClient Setting up a .net object same as in the previous function but setting up a different kind of object this one is a webclient.

$client.Headers.Add("user-agent", "PowerShell"We've got to do a bit of work to this object before we can use it. Web servers get all funny if you don't give them a user-agent string.

$client.downloadfile($path, $localThis does the work and downloads the thing in $path and saves is in $local.

Part 3
So with the functions setup we move into the main bit of the script 

$path = "http://www.cs.wisc.edu/~ballard/bofh/excuses"
$local = "c:\temp\temp.html"

Recognize those variables? Yup we'll be using them right now!

download-file $path $local So we're calling the function setup earlier with the two variables we just created and set. 

$excuse = Get-Content $local | get-random This sets up a variable $excuse and pipes the content of the file we just downloaded to get-random... This will all become clear (if it's not already)

say-text "Today's excuse is... $excuse" Now we call the function we setup at the start and hands it a bit of text. See what it's doing?! Isn't Powershell cool?!

So this is just a quick example of something neat you can do with powershell. One thing to keep in mind is you can copy and paste those functions and use them in other scripts.

Let me know if you have any trouble with this script by leaving a comment below. Also there's a glaring inefficiency in this script so add a comment pointing out what it is if you can, and for even more kudos suggest a more efficient approach!

Lastly full credit for the say-text function should go to http://mckibbins.info/2013/01/21/powershell-text-to-speech/

No comments:

Post a Comment