ScriptBlock Parameters

This was another one of those "Ah Hah!" moments with Powershell. Yesterday Jeffrey Snover wrote up a great post showing how to use ScriptBlocks as parameters in a pipeline.

This reminded me of a great podcast where Scott Hanselman interviewed Bruce Payette. Back when I first listened to it, they were talking about ScriptBlock parameters and it went completely over my head.

Now if you couple their discussion on the podcast with Jeffrey's post, you can come out with some incredibly powerful knowledge and understanding of Powershell.

Also, if you are not listening to Scott's podcast on a regular basis, I have one question for you. Why the heck not? He covers all kinds of great topics from HDTV to web development.

The Powershell Function Directory

Anybody that has been using Powershell has created a function at some point. A function is simply a named ScriptBlock that can accept parameters. Also, you very likely know that there is a Function provider in Powershell. But I am willing to bet a lot of folks haven't used the provider all that much. If I am wrong, I would love to hear some feedback on the topic.

So here I am going to create a basic function and then we will look at what we can do with the function provider to manipulate it.

   1: 6 >  function foo {"Hello $args"}
   2: 7 >  foo world
   3: Hello world

So now that we have a new function we can cd into the function drive as follows. Notice that now we can get some cool info about the function we just created.

   1: 11 >  cd function:
   2: 12 >  ls foo | fl
   5: Name        : foo
   6: CommandType : Function
   7: Definition  : "Hello $args"

Since we are in the function directory, we can rename a function quite easily.

   1: 15 >  rename-item foo bar
   2: 16 >  bar world
   3: Hello world
   5: 17 >  ls foo
   6: Get-ChildItem : Cannot find path 'foo' because it does not exist.
   7: At line:1 char:3
   8: + ls <<<<  foo
   9: 18 >  ls bar | fl
  12: Name        : bar
  13: CommandType : Function
  14: Definition  : "Hello $args"

There is no longer a function called foo but we do have a function named bar with the exact same definition that foo had originally.

Armed with this information, occasionally I like to take a look at what one of my functions looks like.

To do this all I need is to run get-content on a function, or use the alias cat.

   1: 28 >  cat Function:\Add-Assembly
   2: param($name) return [System.Reflection.Assembly]::LoadWithPartialName($name)

WS-Man, Powershell, and MRTG

There's a cool site over at that has some examples of using MRTG (Multi Router Traffic Grapher) coupled with Powershell and Win RM.

There are some Powershell scripts up there that show how to access data with WinRM in Powershell and cast it from XML to a rich PS based object.

Take a look!

Searching Event Logs with Powershell

I recently had  a situation where I needed to be able to search an event log for a particular value.

I wrote a quick little script so that our PM could run it with little effort

   1: param ($name)
   2: $user = '*' + $name + '*'
   3: get-eventlog application | where {$_.Message -like $user} | 
   4: format-list Message,TimeGenerated

I am basically searching for event logs that contain a particular name.

It's pretty straight forward once you find that .Message is what contains the real meat of the event log entry.

You could also obviously use get-eventlog system as well.

Objects or Text in a pipeline ?

Since the release of Powershell there have been a variety of discussions in the community debating which is more powerful, objects or text in a shell environment. Really it depends on what you are managing with  the shell.

In the case of the *NIX world, there is a bunch of configuration files that need to be changed, and for this a text based shell is a great thing. A text based shell to manipulate text is completely appropriate.

The world of Windows is a very different story. Windows was not built around configuration files. It is an OS that is accessed and manipulated using API's and a set of objects. This of course leads into why Windows needs an object based shell.

What is really comes down to is using the right tool for the job. I am not so sure I would want to manage a Linux server with Powershell, nor would I really want to manage windows with bash.

Server Core &#8211; Preparing Your Desktop

I find it amusing that the longest task that occurs the first time you log into Server Core is "Preparing Your Desktop."


I can just here the server now... "where the heck am I going to put that console window anyway?"

Custom Prompt and $NestedPromptLevel

I have had a custom prompt for quite some time now. I am pretty sure I got started with by using the custom prompt from the PowerShell Community Extensions.

I have tweaked it here and there and apparently at some point I dropped the part of the default prompt that used $NestedPromptLevel.

This wasn't a problem until I was reading about some great debugging techniques in PowerShell in Action by Bruce Payette which used the Nested Prompt feature.

This was quickly fixed with the following:

   1: if ($NestedPromptLevel -gt 0) {$myPrompt = "PS-nested >>"}
   2: Write-Host ($myPrompt)  

Now my nested prompt works quite well. When I hit S to suspend, I get dropped into my custom nested prompt.

   1: PS 10 >  notepad
   2: PS 11 >  gps notepad | kill -confirm
   4: Confirm
   5: Are you sure you want to perform this action?
   6: Performing operation "Stop-Process" on Target "notepad (4512)".
   7: [Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): S
   8: PS-nested >> gps notepad
  10: Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
  11: -------  ------    -----      ----- -----   ------     -- -----------
  12:      57       6     2000       9884    78     0.08   4512 notepad
  15: PS-nested >>
  16: PS-nested >>
  17: PS-nested >>
  18: PS-nested >> exit
  20: Confirm
  21: Are you sure you want to perform this action?
  22: Performing operation "Stop-Process" on Target "notepad (4512)".
  23: [Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): Y
  24: PS 14 >

Note to self: when messing with defaults, don't delete stuff when you don't know what they are for.



Confessions of a Powershell Evangelist

For the last year or so I have been trying to get people I work with excited about Powershell. Some people love it right away, but for others, it is a bit overwhelming. That being said, I had an interesting experience the other day. In order to set the context of this, I must confess something.  I have not been a big fan of PowerGui. My attitude was always something like this: "PowerShell is a SHELL, not a GUI, and the last thing in the world that I need is yet another GUI application."

Don't get me wrong here. It's not that I thought PowerGui is a bad application, its just that I personally didn't see the value in it for me and what I was doing with Powershell on a daily basis.

In spite of my point of view, I let my team know that PowerGui had RTM'd and forwarded a link to my co-workers.

Within about an hour I got an email from one of our Operations guys that included the following:


"Dude, this is fricking AWESOME, I installed it with the Active Directory Quest management pack and E2K7 Management tools (32bit) on a Windows 2003 R2 box. Super sweet!"


After reading that my attitude about PowerGui started to change :) Another 4 or 5 hours go by and I get another email from the same person:


"WOW, I have being playing with some of the AD and E2K7 stuff, this tool kicks so much butt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"


I would like end my confession with an apology to Dimitry and the rest of the PowerGui crew.  I just wish I had started telling people about it earlier. You guys have created an awesome tool and it has absolutely helped me in getting more people in my organization using Powershell. Thank you very much for your hard work and all that you give to the Powershell Community.

By the way, I have been a die hard fan of the Quest AD Cmdlets from the very beginning.

As we - the Powershell Community - work together to get people on board with Powershell, we must remember and realize that what works well for us as individuals may not work well for others and vice versa. We must be able to step into the shoes of people we are working with, understand their concerns, and help them solve their problems, (with Powershell of course.)