Playing with Classes in PowerShell v5 Preview

One of the features we’re working on in the latest version of PowerShell is the ability to define custom classes.

If you’ve ever used a PSCustomObject or a Hashtable in a script for storing related data, you’ll probably find classes to be a useful addition to your scripting toolkit.

 

001
002
003
$point = @{ X = 0; Y = 0 }
$point.X = 10
$point.Y = 20

 

While PSCustomObjects and Hashtables let you group related data, what if you want to perform actions on that data? For example:

001
002
$point = @{ X = 0; Y = 0 }
$point.Move(10, 20)

 

This is the kind of scenario that classes really excel at. You use classes for holding “buckets” of related data, and operations on that date.

While the release notes in the V5 Preview (and of course, upcoming actual documentation) give an overview of how to define a class in PowerShell, here’s what they end up looking like:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
class Point
{
    ## Define two properties, using PowerShell’s regular
    ## variable syntax. You can limit variables to a type
    ## using regular type contraints, toos:
    ## [type] $VarName = initialValue
    $X = 0
    $Y = 0

    ## Define a method (that returns void), and takes
    ## two parameters. You can limit the types on these
    ## parameters, of course.
    [void] Move($xOffset, $yOffset)
    {
        $X += $xOffset
        $Y += $yOffset
    }
}

## Create a point and use it
$point = [Point]::new()
$point.Move(10, 20)
$point

 

And in use:

PS C:\temp> c:\temp\point.ps1 | Format-Table -Auto                                                                      
                                                                                                                        
 X  Y                                                                                                                   
 -  -                                                                                                                   
10 20                                                                                                                   
                                                                                                                        
                                                                                                                        

Now, if you wanted to extend this concept far further than you would ever want to, you might get this :)

 

saddle

And Show-BoxDemo in all of its glory. TAB switches between objects, and there are a few other hotkeys in the source.

http://www.leeholmes.com/projects/boxdemo/Show-BoxDemo.ps1

And if you’re curious:

iex(iwr http://www.leeholmes.com/projects/boxdemo/Show-BoxDemo.ps1)

Creating an Easy PowerShell Uptime Monitor

In a recent post, I blogged some data based on an uptime monitor I put together when I started having problems with my (then) web hosting platform.

Here’s how it works.

The first step is a script, Test-Uri. This essentially runs the Invoke-WebRequest cmdlet and captures the important details: Time, Uri, Status Code, Status Description, Response Length (so you can detect drastic content changes or incomplete responses), and Time Taken.

 

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
##############################################################################
##
## Test-Uri
##
## From Windows PowerShell Cookbook (O’Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
##############################################################################

<#
 
.SYNOPSIS
 
Connects to a given URI and returns status about it: URI, response code,
and time taken.
 
.EXAMPLE
 
PS > Test-Uri bing.com
 
Uri : bing.com
StatusCode : 200
StatusDescription : OK
ResponseLength : 34001
TimeTaken : 459.0009
 
#>

param(
   
## The URI to test
    $Uri
)

$request = $null
$time
 = try
{
   
## Request the URI, and measure how long the response took.
$result = Measure-Command { $request = Invoke-WebRequest -Uri $uri
 }
   
$result.
TotalMilliseconds
}

catch
{
   
## If the request generated an exception (i.e.: 500 server
    ## error or 404 not found), we can pull the status code from the
    ## Exception.Response property
    $request = $_.Exception.
Response
   
$time = -1
}

$result = [PSCustomObject] @{
    Time 
= Get-Date
;
    Uri 
= $uri
;
    StatusCode 
= [int] $request.
StatusCode;
    StatusDescription 
= $request.
StatusDescription;
    ResponseLength 
= $request.
RawContentLength;
    TimeTaken 
= $time
;
}

$result

 

The second step automates the invocation of the Test-Uri command, sending its output into a CSV. To do this, you use the Register-ScheduleJob cmdlet. Here’s an example to test your blog every hour:

001
002
003
004
005
006
007
008
009
010
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `
   
-RepetitionInterval (New-TimeSpan -Hours 1
) `
   
-RepetitionDuration ([TimeSpan]::MaxValue)

Register-ScheduledJob -Name blogMonitor -Trigger $trigger -ScriptBlock {
   
$myDocs = [Environment]::GetFolderPath("MyDocuments"
)
   
$outputPath = Join-Path $myDocs blogMonitor.csv
    Test-Uri http://www.leeholmes.com/blog | Export-Csv -Append $outputPath
}

 

As long as your computer has internet connectivity, this is a very reliable approach. And it’s not exactly “big data” – I’ve been monitoring my blog every hour since September 1, 2012 and the CSV is only 1.3MB.

Arvixe Status Report

In 2010, I posted about my woes with WebHost4Life (which I’m shocked is still around.) I looked around for another host, and ended up going with Arvixe. I’ve been happy with them ever since.

In the comments, Sebastian wrote:

Sebastián Cañizares writes:

Arvixe is the same problem … they say “We are currently facing network issues across at least one of our facilities The packet loss is disrupting service” and after 3 months my site still has the problem … the site going up and going down …

I was wondering if I was blind to a problem, so I thought I’d do a bit of digging.

Since learning my lesson with WebHost4Life, I’ve been using a simple PowerShell script to monitor my blog uptime and response time. It’s been running since 9/1/2012.

Caveat: This is running from my house – so the data is actually a combination of:

  • How fast and reliably Arvixe responds to requests
  • How fast and reliably my home connection (Comcast, router, etc.) responds and transmits those requests

In any case, the data I have doesn’t seem to back up what Sebastian says.

Uptime: Out of 12,978 samples, my combined data only failed to get a "200 OK" response code 154 times. So that’s about 99% uptime.

Response times:

  • Until about October 2013, the response times were usually less than 2 seconds. This includes the time that WordPress takes to render the content / etc.
  • After October 2013, most of the response times are still usually less than 2 seconds. However, there has been a secondary band of response times around 5 seconds.

 

image

 

For $6 a month, Arvixe continues to be a great investment.

Handle Hitch Knot for Pulling Thin Rope

If you’ve ever tried to pull hard on thin rope (maybe to tighten slack in a line), you’ve probably wrapped the rope around your hand and felt it dig in as it constricted around your fingers.

Here’s a knot that solves the problem – I call it the Handle Hitch. I couldn’t find it anywhere else – if you’ve heard of it and it has a name, I’d love to know.

With slippery rope (i.e.: paracord), it isn’t suitable for massive loads due to its similarity to the sheepshank. However, it unquestionably improves your ability to grip a line.

Wrap the cord around your hand

The first step is to wrap the cord around your hand. I find it useful to wrap from the outside in.

image

image

 

Create a bight in the exiting rope

And tuck it between your fingers and the series of strands on the back of your hand.

image

image

 

Pull the bight forward

image

 

Create a loop in the standing end

Create this loop in a similar way that you create the loop in a sheepshank. The bight we previously created is on the right, the sheepshank loop is on the left.

image

 

Pass the bight through the sheepshank loop

As you do with the bight in either end of a sheepshank.

image

 

Tighten the sheepshank loop

image

 

Let go of the standing end, and pull

image

 

Once the rope is under tension, it can accommodate medium loads. With paracord, I found the bight would slip out of the sheepshank loop with about 100lbs of pulling force – a similar failure mode to the sheepshank, but far greater than what is comfortable to pull by just wrapping the rope around your hand.

For loads greater than that, you really would want something more secure – for example, using a strong stick or your pocket knife in a Marlinspike hitch.

Here’s a video of tying this knot:

Gregg Shorthand from a regular QWERTY Computer Keyboard

 

Download – Gregg Shorthand Keyboard:

ShorthandKeyboard.exe, 720kb.
ShorthandKeyboard.ahk (AutoHotkey script source, 19kb)

 

 

If you’ve got an interest in languages, writing, and computers – you may have stumbled into the crazy world of Shorthand and stenography. Pitman, Gregg, Teeline, and others.

File:Gregg shorthand A Christmas Carol.jpg

(Image courtesy of Wikipedia)

Pitman shorthand isn’t very practical in modern society because it relies heavily on thick vs. thin lines. Today’s writing instruments offer very little variation in that regard – because the days of the flexible fountain pen have tragically long since passed. (Of course, you could argue that shorthand in general isn’t practical in modern society, but then you wouldn’t be reading this post.)

Gregg shorthand is entirely possible in today’s world of boring pens and pencils. The speed of Gregg Shorthand comes primarily from:

  1. Alternative letter forms that are faster and easier to write than our traditional alphabet.
  2. A list of “brief forms” (abbreviations) for common words. For example, “men.” instead of “morning”.

For the first step, learning the letter forms is quite easy and takes very little practice. For the second step, most of the refinement in Gregg Shorthand over time has primarily been tweaking the brief forms: how many, and what they are. Learning the brief forms is not easy, and takes a lot of memorization and work.

Since shorthand is a skill subject, it requires REGULAR practice, preferably on a daily basis.  Forty-five minutes to an hour a day would be a good goal if you can squeeze it in.

http://shorthandshorthandshorthand.com/Starting_Out.htm

A person writing regular "longhand” can reasonably get to 50 WPM just writing out regular words as fast as they can. Add in a more efficient symbol system, and then you’re maybe at 70 WPM.

Most speed improvement in Gregg Shorthand comes from the second step – learning the brief forms. That’s what will take a stenographer from 50 WPM to 200 WPM.

Now, you may look at these numbers and think – “I can already type 80 WPM longhand!" In that case, you’ve elevated the symbol system speed improvements from our traditional alphabet to another level. Instead of writing the entire outline of letters (or even faster swooshy shapes), you just flick your fingers in a certain way.

To improve either your Gregg Shorthand skills, or regular typing skills, you may be able to increase your speed even further through regular learning and use of brief forms. But how? By integrating it into your regular daily typing, that’s how.

Attached to this post is a simple “Shorthand Keyboard” application to let you do exactly that.

This application converts the 147 Gregg Shorthand Diamond Jubilee brief forms into their longhand equivalents. You can type shorthand all day, but your [email | blog | Twitter | whatever] readers get the English equivalent. If you type the longhand equivalent of a brief form on accident (or you didn’t know it), the application gives you a simple on-screen reminder.

image

So when you type: “Ths application converts the 147 Gregg shorthand diamond jubilee brief forms into their longhand equivalents. U k type shorthand all day, bt u-r [email | blog | Twitter | whatev] readers get the English equivalent. If u type the longhand equivalent o a brief form on accident (or u didn’t know t), the application gives u a simple on-screen reminder”, you get the paragraph above.

The application doesn’t replace the brief forms by default, since that tends to conflict too often with stuff you type regularly. Instead, you press your Caps Lock key, enter the brief form, and then any non-alphabetic character (such as a space or a period).

Minor notes:

  • If you want to combine brief forms (such as You + r = Your), use a dash character: [Caps]u-r[Space] = “your ”
  • If you want your replacement to be capitalized, end it with a right-shift. [Caps]u[Right-Shift][Space] = “You “
  • The Gregg Shorthand dot symbol (to add an “ing” to whatever word you just wrote) isn’t supported, since that conflicts with ending sentences. It is implemented for “men. = morning” and “th. = think”, though, as these are the common ones. “A” and “an” are so quick to type anyways that the dot equivalent is not a useful speed gain.
    Enjoy!

Fixing KeePass’ Slow Startup Performance

If you don’t use a Password Manager to store your login information for websites, first go read this: http://www.troyhunt.com/2011/03/only-secure-password-is-one-you-cant.html.

I’ve been using KeePass for my password manager for years, but noticed that their Professional Edition had a pretty brutal startup delay. As in – launch KeePass and wait 80 seconds for the window to open. While password security is important, that kind of delay will make even the most security-conscious person start thinking about using ‘123456’ for their password instead.

Surprisingly, I hadn’t seen many complaints online (and certainly no solutions), so I decided to see what Process Monitor might say. After setting an application filter for ‘keepass.exe’, here was the answer:

image

At 7:14 and 10 seconds, it starts enumerating the files in the directory where it is installed. And then doing this for every subdirectory. On my machine, that results in processing over 1600 files – as it was a random ‘Tools’ directory with all kinds of junk and support files.

At 7:14 and 55 seconds, it finally completes. And then creates a PluginCache file.

image

If I were a betting man, I’d say that it was looking at each of those 1600 files trying to figure out if they were some sort of KeePass plugin or not. Which takes a long time. This seems even more likely when you load the program a second time. It doesn’t take nearly as long to start because computers are quicker to read files a second time with the assistance of filesystem and hard drive caches.

Fortunately, this is simple to verify:

image

After rebooting to clear the caches (there are more elegant ways), our suspicions are confirmed. Only 2 seconds to launch – the highlighted line is when Keepass brought up its UI:

image

So there are two solutions:

Disable Plugins

If you don’t need plugins, you can just disable them.

Move KeePass

If you need / want plugins, create a subdirectory in your Tools directory for KeePass. For example, c:\Users\Lee\Tools\KeePass. When KeePass launches, it will still scrub through that whole directory and its subdirectories – but there will only be a few files there. Then, put a launcher script in your Tools folder:

:: keepass.cmd

start %~dp0\keepass\keepass %*

Texting Yourself Sports Alerts with PowerShell

You’ve probably been in the situation of wanting to alert yourself when any update happens to a sports game, UPS package tracking status, or something else.

By combining Invoke-WebRequest’s beautiful support for HTML parsing with Send-MailMessage’s ability to send email messages – this becomes incredibly easy and useful.

(Note: this script also uses Watch-Command, a script from the PowerShell Cookbook.)

 

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
$content = ""
while($true
)
{
   
Watch-Command -ScriptBlock
 {

        ## Fetch the current box score for the game
        $r = Invoke-WebRequest http://www.tsn.ca/MENS_WORLD/scores/boxscore/?id=2388586

        ## The score is in a DIV with the class ‘boxScoreBg’, almost certainly different
        ## for your scenario
        $result = $r.ParsedHtml.Body.getElementsByClassName("boxScoreBg"
)

        ## Extract out what text you care about
        $SCRIPT:content = (@($result)[0].innerText -split "`r`n" | ? { $_ })[5..6] -join "`r`n"

        ## And use that to monitor
        $SCRIPT:content

    } -UntilChanged -DelaySeconds 30

    ## Every cell provider has an email address that you can send to
    ## so that it will be delivered as a text message.
    $params =
 @{
        To 
= "4255551212@txt.att.net"
        From = "my.email@host.com"
        Subject = "Hockey Score Update"
        Body = $SCRIPT:content
        SmtpServer = "mysmtpserver"
    }

    Send-MailMessage @params
}

Using PowerShell to Compare / Diff Files

If you’ve tried to diff files in PowerShell before, you might have seen the Compare-Object cmdlet. The Compare-Object cmdlet lets you compare two sets of items, giving you a report on the differences between those two sets:

PS G:\lee\tools> cd c:\temp
PS C:\temp> $set1 = "A","B","C"
PS C:\temp> $set2 = "C","D","E"
PS C:\temp> Compare-Object $set1 $set2

InputObject SideIndicator
———– ————-
D           =>
E           =>
A           <=
B           <=

From this output, we can see that “A” and “B” only show up in $set1, while “D” and “E” only show up in $set2. For sets of objects, this is all you need to know.

However, one common “set of objects” that people like to compare are lines in text files. When you are comparing lines in a file, you usually don’t care only about the lines that have been added or deleted. You care about where in the file they got added – a situation usually handled by a special-purpose tool such as WinMerge, ExamDiff, WinDiff, or simply the Windows port of diff.exe.

Special-purpose file comparison tools have lots of tricks to compare files efficiently and logically, but PowerShell does let you implement a basic file comparison through a special trick – realizing that the Get-Content cmdlet tags its output objects with the line number they came from.

PS C:\temp> (Get-Content .\test.txt)[5] | Format-List * -Force

PSPath       : C:\temp\test.txt
PSParentPath : C:\temp
PSChildName  : test.txt
PSDrive      : C
PSProvider   : Microsoft.PowerShell.Core\FileSystem
ReadCount    : 6
Length       : 0

That gives the nifty one-liner:

PS C:\temp> Compare-Object (Get-Content files.txt) (Get-Content files2.txt) |
    Sort { $_.InputObject.ReadCount }

InputObject                                                      SideIndicator
———–                                                      ————-
-a—        11/26/2013   9:52 PM          0 files.txt       … <=
-a—        11/26/2013   9:52 PM      75702 files.txt       … =>
-a—        11/26/2013   9:52 PM          0 files2.txt      … =>

If you want to pretty up the output a bit and make the syntax cleaner, let me introduce Compare-File:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
##############################################################################
##
## Compare-File
##
##############################################################################

<#
 
.SYNOPSIS
 
Compares two files, displaying differences in a manner similar to traditional
console-based diff utilities.
 
#>

param(
   
## The first file to compare
    $file1,
   
   
## The second file to compare
    $file2,

    ## The pattern (if any) to use as a filter for file
    ## differences
    $pattern = ".*"
)

## Get the content from each file
$content1 = Get-Content 
$file1
$content2
 = Get-Content $file2

## Compare the two files. Get-Content annotates output objects with
## a ‘ReadCount’ property that represents the line number in the file
## that the text came from.

$comparedLines = Compare-Object $content1 $content2 -IncludeEqual |
    Sort-Object { $_.InputObject.
ReadCount }
   

$lineNumber = 0
$comparedLines | foreach
 {

    ## Keep track of the current line number, using the line
    ## numbers in the "after" file for reference.
    if($_.SideIndicator -eq "==" -or $_.SideIndicator -eq "=>"
)
    {
       
$lineNumber = $_.InputObject.
ReadCount
    }
   
   
## If the text matches the pattern, output a custom object
    ## that displays text like this:
    ##
    ## Line Operation Text
    ## —- ——— —-
    ## 59 added New text added
    ##
    if($_.InputObject -match $pattern
)
    {
       
if($_.SideIndicator -ne "=="
)
        {
           
if($_.SideIndicator -eq "=>"
)
            {
               
$lineOperation = "added"
            }
           
elseif($_.SideIndicator -eq "<="
)
            {
               
$lineOperation = "deleted"
            }
               
           
[PSCustomObject]
 @{
                Line 
= $lineNumber
                Operation = $lineOperation
                Text = $_.InputObject 
            }
        }
    }
}

Getting Started with Guitar

If you’re interested in learning guitar, you might be running into an enormous feeling of dread. How do you get started? What kind of guitar should you get?

Here’s a short guide that can hopefully help get you started.

Buying a Guitar

Guitars can get really expensive. But higher-end guitars end up being a matter of taste (both musically and aesthetically). For your first guitar, you don’t have an opinion, so there’s no need to splurge. After all, you might find out that you don’t end up liking guitar in the end.

For your first guitar, my suggestion is to start relatively cheap. You can get really nice guitars for under $200 (i.e.: your local Guitar Center), and they’ll last anybody for many years in the hobby. The guitar people at the local shops know how to play guitar, so you can even ask them to play the different guitars a bit so you can hear which ones sound nicest to your tastes. They are always really helpful – and if you go on a weeknight, you basically have their undivided attention :)

Also, remember that you won’t be the first one to come to the store with this conundrum. If you go in with a budget, they’ll really be able to help you find the guitar that’s best for you.

I watched a bunch of ‘Buying a new guitar’ YouTube videos, this one represents the situation pretty well: http://www.youtube.com/watch?v=iDz0W8UNgn4.

The one thing they don’t explicitly mention that you want to test with a guitar is making sure every note plays properly. Sometimes, they have issues where the notes at one end of the neck sound great, but as you go through the middle of the neck (or something), they’ll start sounding with a buzz. Sometimes, this is player fault. Sometimes, it’s just something that is due to being set up incorrectly (which can be resolved.) Sometimes, it’s a flaw in the guitar.

If a guitar has fret buzz before being set up by the store, it’s usually a bad sign. They may be able to fix the buzz, but might do so in a way that makes the guitar harder to play in the long run – for example, by raising all of the strings (which makes the guitar harder to play).

Learning to Play

Once you’ve got your brand new guitar (and maybe had it set up), the fun part begins!

Chords

The easiest way to start is to learn how to play guitar chords. These are patterns that you play on the neck of the guitar that sound nice when you strum all (or most) of the strings. YouTube has a lot of great tutorials. Once you start getting good at some, you can start to play along with songs you like – for example: http://www.youtube.com/results?search_query=%22let+it+be%22+guitar+chords. Print out a crib sheet of guitar chords, keep it nearby, and start practicing.

Tab

You can follow along with random YouTube users, but one common way to share musical knowledge is called Tablature – aka "Tab". There is tons of it on the internet. It is usually written as the song’s lyrics, with the chords you need written over the word where you start to strum it:

let_it_be_tab

Listen to songs, play along, and learn to sing along if you are so blessed :)

Keep on Growing

As you learn, it’s easy to get stuck in "bedroom guitar" mode, where you grind on songs alone, get stuck on things, and don’t know where to go next. A next great step is to get a guitar tutor. They are usually $30-$50 per hour, so you can take a lesson every week or two.

In the beginning, you can start with a teacher that is a generalist. Music stores often have recommendations on local tutors (or instructors that rent out space in the local shop), and that is a great place to start. Take trial lessons with a handful of teachers, and find the one that matches your learning style.

A good teacher should push you hard enough that you need to spend a couple of hours on practice for each hour of instruction. If not, you’re just paying to listen to them talk. If that’s happening, there are much more efficient ways to blow your money so go do that instead.

Once you get more accomplished, you might find you like some kinds of music more than others. If that’s the case, you can always specialize – so you can find teachers that focus on Jazz, Classical guitar, Rock, or whatever else interests you.

At some point, tablature isn’t descriptive enough – and your teacher will introduce you to standard music notation.

notes

Standard music notation is challenging to learn at first, but does open your world to a whole new kind of music sharing and knowledge.

In the end, the biggest requirement for growth is practice. If you wonder how long it’ll take you to become a master shredder, you’d better become deeply familiar with the 10,000 hour rule.

Who’s in Your Email Social Network?

Have you ever wondered who’s in your “Email Social Network”?

I was wondering the other day how to find out who I mail the most. With a bit of PowerShell scripting, the answer is a breeze to find out:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
## Connect with Outlook, and open the ‘Sent Items’
$olApp = New-Object -com Outlook.Application 
$namespace = $olApp.GetNamespace("MAPI")
$sentItems = $namespace.GetDefaultFolder(5)

## Go through each item, split out names when there were multiple
## recipients, and clean them up a bit

$sentEverTo = $sentItems.Items | % { $_.To -split ";" } | % { $_.Trim(" ‘") }

## Group by how often you’ve sent mail to them
$sortedTo = $sentEverTo | group

## Explore
$sortedTo | sort Count