imageLast weekend I did two talks at SQL Saturday #89: one on StudioShell that seemed well-received, and another titled “Stupid PowerShell Tricks” that was basically an hour of laughter and learning.  Many thanks to the volunteers and sponsors, and to everyone who attended for all of their positive energy.

As I promised the attendees, this post will outline each of the techniques I demonstrated during “Stupid PowerShell Tricks.”  First though, some background…

What is a Stupid PowerShell Trick?

As I defined it in the session, a Stupid PowerShell Trick is any PowerShell element that has the potential to make your life or work easier.  These are not full solutions to exact problems, but rather small techniques you can employ in various situations.

The idea for the session came to me after going over some notes for previous PowerShell and StudioShell sessions.  I found that the most frequent and at times energetic question from the audience was:

What was that you just did there?

Most of the time this question was shouted in response to some shortcut I have built-in to my session instead of the main point of the presentation.  Turns out, I have more than enough of these little things to create a talk around them!

And the name?  It’s a derivative (read:ripoff) from David Letterman’s Stupid Human Tricks:

You may never need it, but if you ever need to stop a fan with your tongue, its empowering to know that you can.

So without further ado, here are the tricks I presented at SQL Saturday #89:

Trick #1: push-project

This is one of those personal work-habit shortcuts that integrates well with PowerShell.  I organize my work under a single Project folder in My Documents.  The name of each folder is typically the client for whom the work is being done, the name of an open-source project, etc.  This makes finding the project from the shell easy – I just navigate to the project folder and add the name of the project to the path:

1 # navigating to a project folder 2 PS> cd ~\documents\project\MyAwesomeProject

That’s an awful lot of typing though, and the only piece that changes is the name of the project.  So, I added a push-project function to my profile script that lets me navigate to these locations with less fuss and tabbing:

1 function push-project( $project ) 2 { 3 pushd ~/documents/project/$project; 4 } 5 6 New-Alias -Name pp -Value push-project;

In addition, an alias associates the shorter ‘pp’ to the push-project function, allowing me to navigate to a project with the much shorter:

1 PS> pp MyAwesomeProject

Yeah, like I said, the tricks are stupid.  But this saves me countless keystrokes a day and I move from client to client, project to project.

An Even More Stupider Trick

An audience member (can’t recall his name) had an awesome suggestion – assume $project is a pattern to match against the project names!  Turns out this no-brainer was easy as pie to pull off:

1 function push-project( $project ) 2 { 3 $path = "~/documents/project/$project" 4 if( -not( Test-Path $path ) ) 5 { 6 $path = ls ~/documents/project ` 7 -Filter "$project*" | select -First 1 ; 8 } 9 pushd $path; 10 }

Line 3 defines a full project path string using the input from the user in the $project variable.  Line 4 tests whether this path exists; if the path does not exist, it is assumed that the project name is incomplete, and lines 6-7 search the project tree for the first matching project name.  Line 9 completes the function by pushing the full project path onto the location stack.  In the end, getting to my projects has never been so tight:

1 PS> pp my

Trick #2: invoke-item

This next trick is a PowerShell gimmie – it’s built right in to the default session configuration.

There may be times when you want to open a text file, word doc, spreadsheet, etc from the console.  You can always invoke the program directly:

1 PS> excel supersecretdata.xls 2 PS> word supersecretdata.doc 3 PS> notepad supersecretdata.txt

But then you have to know what program to run; e.g., you can’t open a spreadsheet in notepad and expect to be able to read it.  So why not let PowerShell figure it out for you – use the invoke-item cmdlet to invoke the default shell action for a given file:

1 PS> invoke-item supersecretdata.xls 2 PS> invoke-item supersecretdata.doc 3 PS> invoke-item supersecretdata.txt

The example above will open each file in the appropriate application.  No fuss no muss.

“But Jim,” you say, “that’s a lot of typing!  Oh how I wish there was some way to accomplish this without all those keystrokes!”

Fear not PowerShell trickster!  There is an alias you can use:

1 PS> ii supersecretdata.txt

One of the more useful cases for this trick is when I want to open explorer at my current location in the shell.  Easily done:

1 PS> ii .

This takes advantage of the fact that the default action for a folder in Windows is to display it in explorer.  The dot in the command represents the “current path location,” which is always a folder.

Trick #3: PowerShell Here

imageThis one plays compliment to the previous trick.  Sometimes I need a PowerShell prompt open in the folder I’m looking at in explorer.  For that I use the PowerShell Here registry hack from Scott Hanselman’s blog.

This hack adds a PowerShell Prompt Here entry into the context menu for file folders.  Clicking the menu item will, as you’d expect, crack open a new PowerShell console that is pre-navigated to the correct folder. 

Super-handy to have when you need it.

Trick #4: Use VIM

imageVIM is a super-handy text editor that can run inside of your PowerShell console session.  Wait, let’s go over that again: it’s a text editor that runs inside of your PowerShell console.

VIM’s been around for … well, forever basically, in one form or another.  It’s a cross-platform port of the Unix VI tool, and it works the same in Windows, Linux, MacOS, you name it.

Mind you, I’m not at the point where VIM is my editor of choice – but when I need to make a quick edit to a file while I’m working in the shell it’s sooOOOoooo much faster to jump in and out of VIM than it is to bounce from the shell to notepad or PowerGUI and back to the console again.  My hands stay on the keyboard, which reduces the chance of my RSI coming back.

Now, VIM’s no picnic, but the juice is well worth the squeeze.  I highly recommend bookmarking the VIM docs, printing out some cheat sheets and jumping in.

Trick #5: clip

These last three tricks all have to do with pushing data someplace.

The first trick uses a built-in windows application named clip.exe to move data from PowerShell to any other application through the clipboard.  Very handy little trick:

1 PS> ls | clip

This example copies the list of files and folders in the current directory to the clipboard.  You can paste the list in any program – notepad, word, email, etc.

Of course you’re not limited to file lists – perhaps you need to add a list of event log entries in an email to some vendor support engineer:

1 PS> get-eventlog application -newest 20 | clip

Or maybe you need to copy the contents of a file:

1 PS> get-content myapplog.txt | clip

Or a list of every PowerShell variable name and value:

1 PS> dir variable: | clip

Or… oh whatever, you get the point.

Trick #6: out-gridview

Another trick to get data out of the console…

There is a handy built-in PowerShell command called out-gridview.  PowerShell n00bs tend to really like this command because it produces a UI – specifically a nice WPF grid displaying whatever data you pipe it.

Rather than show you what this does, I’d rather you play with it for yourself – take the examples from Trick #5 and replace “clip” with “out-gridview” and see what happens.

This one is really great when you want some data to hang around while you execute other commands.  The console is awesome, but the output doesn’t stick around too long. 

Trick #7: out-voice

And finally, the piece de resistance, the coup de gras, the penultimate of the first round of Stupid PowerShell Tricks – I present to you in all its glory … out-voice.

A few months back @shaylevy posted a little gem that demonstrated the use of the Microsoft Speech API from PowerShell.  I’ve already blogged a bit about it, and how using PowerShell to explore new APIs is both fun and rewarding.  This trick is basically an extension of that tweet from Shay.

One day I was working on a rather convoluted build while trying to help my daughter with some math facts.  The build took a long time to run - I wanted to give my little girl the full attention she deserved, but I also needed to get this build out.  So I rigged up a way for the computer to tell me when the build was completed.  This way, I can ignore my computer the way my daughter deserves, and still know exactly when the build has completed.

I added this code to my profile script:

1 $voice = New-Object -ComObject SAPI.SPVoice 2 $voice.Rate = -3 3 4 function invoke-speech 5 { 6 param([Parameter(ValueFromPipeline=$true)][string] $say ) 7 8 process 9 { 10 $voice.Speak($say) | out-null; 11 } 12 } 13 14 new-alias -name out-voice -value invoke-speech;

The $voice variable is set to a Speech API COM object in line 1.  Line 4 defines a function named invoke-speech; the param statement on line 6 and the process block on lines 8-11 allow this function to receive pipeline input.  The magic happens on line 10, where the input passed to the function is sent to the speech API for processing.  Line 14 aliases the command out-voice to the new function.

So how did this help me know the build was done?  Easy!  Add the above code to your session and try this:

1 PS> 'Hey beef, the build is done!' | out-voice

This is a great trick ignoring your computer during long-running processes:

1 # pretend this is a long-running process 2 sleep -seconds 5 3 "all done!" | out-voice

And, as the audience pointed out, the potential for abuse is significant.  Next time you leave for lunch, run this little quip, replacing my name with the name of your least-favorite coworker:

1 PS> while(1) { 2 sleep -seconds (get-random -min 90 -max 500); 3 'Jim, I need you over here now' | out-voice; 4 }

The ideas grow unbound from this point.  Read a file:

1 get-content myfile.txt | out-voice

Read the event log:

1 get-eventlog -log application | out-voice

… and so forth.

Conclusions

Stupid?  Maybe.

Useful?  Certainly.

Fun?  Oh yeah.  I highly anticipate you blogging on your own Stupid PowerShell Tricks; send me a link through the contact form or add a comment with a link to your blog!