Stupid PowerShell Tricks #1

§ September 20, 2011 07:01 by beefarino |

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!



Summer (and Fall) of Speaking

§ September 12, 2011 03:10 by beefarino |

SOOOOoooooOOOO… I’ve been a bit incognito lately and I thought I’d take a moment to summarize what’s been happening in the last three months,and give everyone a head’s up for the rest of the year.

May was consumed largely by two things.  The first was volunteer work at my kids’ school during EOG testing.  I was basically there for 5 hours every day for three weeks, so the teachers could administer 4 exams for each of their 24 students one-on-one as mandated by the school board.  I couldn’t stop the testing, but I did what I could to ease the pain on the school, teachers, and kids.  The second thing was prepping talks for the summer conferences – CodeStock, MADExpo, and DEVlink – and various code camps in the Carolinas and Georgia.  I headed out to CodeStock at the end of May, where I spoke about StudioShell; it was another fantastic conference experience, the highlight for me was getting to kick Charles Petzold out of the room so I could give my talk immediately after his.  I mean, freaking Charles Petzold.

June was full of CodeStock and MADExpo.  MADExpo went off rather well for a first-time conference.  The maker-esque focus is something I hope they elaborate upon next year – the sessions on netduino, robotics, and the like were a real hit across the board, and the kid’s area was a blast with snap circuits, legos, etc.  I’m considering submitting an origami session next summer, just to do something completely different…

July was comprised of work, work, work … and a vacation in the east Texas desert, during which I managed to line up a substantial contract that consumed most of August … except of course for DEVlink.  This was my first DEVlink experience and it was a good one (despite the lack of wireless and cell coverage and no, I didn’t stay at the Choo-Choo either).  I definitely made more connections – social and professional – at DEVlink than at any other conference thus far.  I did another StudioShell session there.  Jaws hit the floor, it was well-received.  I also attended PowerShell sessions by other speakers –  Sarah Dutkiewicz and Joe Webb – I love seeing how different people approach teaching this technology to others.

With the summer over and school back in session, my speaking focus is shifting back to user groups and events.  This Thursday, September 15, I’ll be speaking at the WNC .NET User Group about PowerShell for Developers.  I’ve expanded this talk to include PSake, Pester, and StudioShell; I look forward to the feedback on the new topics.

Then on Saturday, September 17th, it’s SQL Saturday #89 in Atlanta.  This will be my first SQL Saturday ever, and I’m so glad to be bringing the PowerShell and development love to the database community.  I have two sessions – the first is using StudioShell to automate Denali, and the second is a brand-spankin’ new talk titled “Stupid PowerShell Tricks”.  I got the idea from going over some of my other talks and realizing that the most frequent question I get asked is “What was that you just did there?”  I also find myself asking this question quite a bit of others – especially when I’m around admins or DBAs.  Since there is obviously much we can learn from each other, I decided to make a session out of it.  I’ll show you my stupid tricks and you show me yours, and we’ll all walk away with new ways to get stuff done!

Later this month – September 22nd to be exact - I’m heading to the Triad Developer’s Group to spread more PowerShell love to Carolina software developers.  In October it looks like I’ll be a guest on Talk TechNet (details to follow).  In November I’m heading up to the Raleigh .NET User Group to demo and discuss StudioShell.

Whew… at some point I’ll need to fit in some project work… I’ve got a couple of decent irons in the fire, some will go open-source and some won’t … more on that in another post…



grok-posh: Interactive .NET

§ May 5, 2011 01:51 by beefarino |

grokbulb1

This post is part of my grok-posh series describing why developers should learn PowerShell.

A PowerShell console is basically an doorway into the entire realm that is .NET, COM, and WMI.  As I say in my talks – you can think of PowerShell as an interactive way to discover, obtain, and manipulate objects.

This makes it a great place to explore the things you can do and to learn about these objects by manipulating them.

Here’s a great example - the other day @shaylevy posted this little gem on twitter:

$error | % { (New-Object -ComObject SAPI.SPVoice).Speak($_.Message) }

Shay’s code is using the Microsoft Speech API to have the computer “read” the error message(s) raised by the last PowerShell command executed.  Slick.

I’ve never played with the Speech API.  Let’s see how I can use PowerShell to interactively learn what I can do with this object:

1 PS > $voice = New-Object -ComObject SAPI.SPVoice 2 PS > $voice | get-member 3 4 5 TypeName: System.__ComObject#{269316d8-57bd-11d2-9eee-00c04f797396} 6 7 Name MemberType Definition 8 ---- ---------- ---------- 9 DisplayUI Method void DisplayUI (int, string, string, Variant) 10 GetAudioOutputs Method ISpeechObjectTokens GetAudioOutputs (string, string) 11 GetVoices Method ISpeechObjectTokens GetVoices (string, string) 12 IsUISupported Method bool IsUISupported (string, Variant) 13 Pause Method void Pause () 14 Resume Method void Resume () 15 Skip Method int Skip (string, int) 16 Speak Method int Speak (string, SpeechVoiceSpeakFlags) 17 SpeakCompleteEvent Method int SpeakCompleteEvent () 18 SpeakStream Method int SpeakStream (ISpeechBaseStream, SpeechVoiceSpeakFlags) 19 WaitUntilDone Method bool WaitUntilDone (int) 20 AlertBoundary Property SpeechVoiceEvents AlertBoundary () {get} {set} 21 AllowAudioOutputFormatChangesOnNextSet Property bool AllowAudioOutputFormatChangesOnNextSet () {get} {set} 22 AudioOutput Property ISpeechObjectToken AudioOutput () {get} {set by ref} 23 AudioOutputStream Property ISpeechBaseStream AudioOutputStream () {get} {set by ref} 24 EventInterests Property SpeechVoiceEvents EventInterests () {get} {set} 25 Priority Property SpeechVoicePriority Priority () {get} {set} 26 Rate Property int Rate () {get} {set} 27 Status Property ISpeechVoiceStatus Status () {get} 28 SynchronousSpeakTimeout Property int SynchronousSpeakTimeout () {get} {set} 29 Voice Property ISpeechObjectToken Voice () {get} {set by ref} 30 Volume Property int Volume () {get} {set} 31

Line 1 creates a new instance of the SAPI.SPVoice object in the shell variable $voice.  Line 2 passes the $voice variable to the get-member cmdlet, which outputs all the methods and properties that the COM object supports.

Lots of opaque methods there – some UI elements it looks like, some asynchronous hooks.  Looks like we can change the rate at which the speech is spoken, the volume, oooohhh – looks like there are other voice options too!  Let’s see what voices we have available:

PS > $voice.GetVoices() Id DataKey Category -- ------- -------- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Token... System.__ComObject System.__ComObject

Aw, sad trombone …  we have only one voice available.  Hey, what’s it sound like anyway?

PS > $voice.Speak( 'Hello Beef!' )
Hello yourself!  Not bad.  What does that Rate property do?

PS > $voice.Rate 0 PS > $voice.Rate = 5 PS > $voice.Speak( 'The build has failed!' ) 1 PS > # oh dear, that has the potential to raise my stress level PS > # let's try to get more of a southern drawl going... PS > $voice.Rate = -5 PS > $voice.Speak( 'Oh no! The build, she has failed!' ) 1 PS > # now that's more like it!

Neat.  As much fun as I’m having, I’m learning a bit about the Speech API.  PowerShell allows me to interact with the object, trying things out and testing theories.  Will I eventually need to turn to MSDN if I want to do anything serious?  Probably.  But consider what I’ve learned so far using nothing but PowerShell for about 60 seconds:

  1. I know the methods and properties exposed by the Speech API voice object;
  2. I know that voices are somehow linked to my registry, and the API suggests that it’s possible to install and remove voices, or create my own;
  3. Based on the methods of the voice object, I can assume there is a way to have the API generate speech asynchronously;
  4. I can manipulate the properties of a voice to my liking.  In fact, using PowerShell I can get immediate feedback on what the voice sounds like.

You can generalize this interaction to almost any object if you know a few key PowerShell cmdlets.  Here I use these key cmdlets to discover how I can work with windows services in my PowerShell session:

1 PS >#what commands apply to services? 2 PS >get-command *service 3 4 CommandType Name Definition 5 ----------- ---- ---------- 6 Cmdlet Get-Service Get-Service [[-Name] <String[]>] [-ComputerName <String[]>] [-DependentServices... 7 Cmdlet New-Service New-Service [-Name] <String> [-BinaryPathName] <String> [-DisplayName <String>]... 8 Cmdlet Restart-Service Restart-Service [-Name] <String[]> [-Force] [-PassThru] [-Include <String[]>] [... 9 Cmdlet Resume-Service Resume-Service [-Name] <String[]> [-PassThru] [-Include <String[]>] [-Exclude <... 10 Cmdlet Set-Service Set-Service [-Name] <String> [-ComputerName <String[]>] [-DisplayName <String>]... 11 Cmdlet Start-Service Start-Service [-Name] <String[]> [-PassThru] [-Include <String[]>] [-Exclude <S... 12 Cmdlet Stop-Service Stop-Service [-Name] <String[]> [-Force] [-PassThru] [-Include <String[]>] [-Ex... 13 Cmdlet Suspend-Service Suspend-Service [-Name] <String[]> [-PassThru] [-Include <String[]>] [-Exclude ... 14 15 16 PS >#looks promising. what does get-service do? 17 PS >get-help get-service 18 19 NAME 20 Get-Service 21 22 SYNOPSIS 23 Gets the services on a local or remote computer. 24 25 26 SYNTAX 27 Get-Service [[-Name] <string[]>] [-ComputerName <string[]>] [-DependentServices] [-Exclude <string[]>] [-Include <string[]>] [-RequiredServices] [<CommonParameters>] 28 29 Get-Service -DisplayName <string[]> [-ComputerName <string[]>] [-DependentServices] [-Exclude <string[]>] [-Include <string[]>] [-RequiredServices] [<CommonParameters>] 30 31 Get-Service [-InputObject <ServiceController[]>] [-ComputerName <string[]>] [-DependentServices] [-Exclude <string[]>] [-Include <string[]>] [-RequiredServices] [<CommonParamete 32 rs>] 33 34 35 DESCRIPTION 36 The Get-Service cmdlet gets objects that represent the services on a local computer or on a remote computer, including running and stopped services. 37 38 You can direct Get-Service to get only particular services by specifying the service name or display name of the services, or you can pipe service objects to Get-Service. 39 40 41 RELATED LINKS 42 Online version: http://go.microsoft.com/fwlink/?LinkID=113332 43 Start-Service 44 Stop-Service 45 Restart-Service 46 Resume-Service 47 Suspend-Service 48 Set-Service 49 New-Service 50 51 REMARKS 52 To see the examples, type: "get-help Get-Service -examples". 53 For more information, type: "get-help Get-Service -detailed". 54 For technical information, type: "get-help Get-Service -full". 55 56 57 58 PS >#ok, now let's see what we can do with a service... 59 PS >get-service | get-member 60 61 62 TypeName: System.ServiceProcess.ServiceController 63 64 Name MemberType Definition 65 ---- ---------- ---------- 66 Name AliasProperty Name = ServiceName 67 RequiredServices AliasProperty RequiredServices = ServicesDependedOn 68 Disposed Event System.EventHandler Disposed(System.Object, System.EventArgs) 69 Close Method System.Void Close() 70 Continue Method System.Void Continue() 71 CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType) 72 Dispose Method System.Void Dispose() 73 Equals Method bool Equals(System.Object obj) 74 ExecuteCommand Method System.Void ExecuteCommand(int command) 75 GetHashCode Method int GetHashCode() 76 GetLifetimeService Method System.Object GetLifetimeService() 77 GetType Method type GetType() 78 InitializeLifetimeService Method System.Object InitializeLifetimeService() 79 Pause Method System.Void Pause() 80 Refresh Method System.Void Refresh() 81 Start Method System.Void Start(), System.Void Start(string[] args) 82 Stop Method System.Void Stop() 83 ToString Method string ToString() 84 WaitForStatus Method System.Void WaitForStatus(System.ServiceProcess.ServiceControllerStatus desiredStatus), System.Void WaitForStatus(System.ServiceProcess.Se... 85 CanPauseAndContinue Property System.Boolean CanPauseAndContinue {get;} 86 CanShutdown Property System.Boolean CanShutdown {get;} 87 CanStop Property System.Boolean CanStop {get;} 88 Container Property System.ComponentModel.IContainer Container {get;} 89 DependentServices Property System.ServiceProcess.ServiceController[] DependentServices {get;} 90 DisplayName Property System.String DisplayName {get;set;} 91 MachineName Property System.String MachineName {get;set;} 92 ServiceHandle Property System.Runtime.InteropServices.SafeHandle ServiceHandle {get;} 93 ServiceName Property System.String ServiceName {get;set;} 94 ServicesDependedOn Property System.ServiceProcess.ServiceController[] ServicesDependedOn {get;} 95 ServiceType Property System.ServiceProcess.ServiceType ServiceType {get;} 96 Site Property System.ComponentModel.ISite Site {get;set;} 97 Status Property System.ServiceProcess.ServiceControllerStatus Status {get;} 98 99 100 PS > 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

The key PowerShell commands: get-command (line 2), get-help (line 17), and get-member (line 59) help you find the objects you’re looking for and tell you what it is they can do.



Why Developers Need to Know PowerShell

§ May 5, 2011 00:23 by beefarino |

smartbulbA few weeks back a colleague of mine asked a great question on twitter:

powershell sounds cool, but i don't use it. why should i learn as a dev?

This is the question I’ve been trying to answer for the development community at user groups and conferences for the last two years.  The short answer is that groking PowerShell makes your life easier.  Technically this is true for any Windows user, so let’s explore the benefits that are specific to developers…

This “grok-posh” series of posts will outline why you should get familiar with PowerShell now.  Some of these will be specific to developers, some more general to powerusers.  As I complete posts I’ll update the links below.

  • Interactive .NET
  • Awesome Build and Test Tools
  • Typing is Faster than Searching
  • It’s Glue that Sticks to Everything
  • Windows Management and Support
  • Agile Applications (no, not that Agile, the other Agile from the 90’s)
  • Immediate Integration with Awesome Tools
  • Command Pattern Platform
  • Repository Pattern Platform

If there is anything you think should be added to this list, please drop me a note via the contact form or twitter.