PowerShell Feature Request: Extended PowerShell type for Help Topics data

I’ve spend a lot of time over the past 6 months exploring the PowerShell help system and the objects it exposes in great detail.  Part of this was to learn PowerShell, and part of this was to get the information I needed for my Integrated PowerShell Help PowerPack for PowerGUI.  While doing this work, it was really clear how much value is added by having the help system accessible through PowerShell itself (more on that in another post).  But there was one small thing that seemed lacking in the first implementation of the help system, hence this feature request.

I’d like to request that the help information for general topics (Get-Help -Category HelpFile) be defined as rich .NET objects similar to MamlCommandHelpInfo.  Currently when you pull up help for a general topic, the object you get back is of type System.String.  This can be seen through the following script:

Get-Help about_alias | Get-Member

This string contains the contents of the file corresponding to the general topic you requested help information for, and if you have the PowerShell Multi User Interface Language Pack installed it will be in the language of the current PowerShell session.  This differs from the other help in PowerShell, such as help for cmdlets.  When you pull up help for a cmdlet, the object you get back is of type MamlCommandHelpInfo.  This can be seen through the following script:

Get-Help Get-Command | Get-Member

This will also be displayed in the language of the current PowerShell session, however there is an important distinction between this and the help information returned for general topics.  In general day-to-day use within PowerShell you won’t notice the difference because when you request this help information it is simply returned to you in the console.  Where the difference becomes apparent is when you’re using PowerShell script to access help information, you want that script to support all languages that PowerShell has been localized to, and you want to format it differently or you want to extract a subset of the documentation from it.

If you’re reading help documentation for cmdlets from PowerShell using PowerShell script, the object returned has properties containing each of the sections you would see when requesting full help information (e.g. Get-Help Get-Command -Full).  This includes Name, Synopsis, Syntax, Detailed Description, Parameters, Input Type, Return Type, Remarks, Examples and Related Links.  Writing a script for this that supports localized versions of PowerShell is facilitated through the use of these parameters because you can get each separate part of the documentation in the language of the PowerShell session programmatically.

If you’re doing the same thing for general topics, you can’t access the different sections of the help documentation because you don’t have rich .NET objects containing properties with the different.  Instead you have to parse the documentation programmatically, which isn’t too difficult in Western languages but including support for Eastern languages becomes quite a challenge, to say the least.

Having the help documentation for general topics returned as objects similar to MamlCommandHelpInfo would make life much easier when supporting multiple languages while accessing this documentation using PowerShell scripts.  This isn’t very high on my priority list, but it would definitely be nice to have.

Kirk out.

Technorati Tags: , , ,

My apologies if your comment didn’t get posted

Being new to blogging, and newer to WordPress, I currently have comment moderation activated and comment spam filtering enabled.  What I didn’t realize was that this means I won’t be notified when a comment is posted that was deemed to be spam.  Since comments deemed to be spam are automatically deleted after a period of time, I noticed today that someone posted a comment on my blog that was automatically deleted but I can’t tell who it was or what the comment said because I didn’t notice early enough to let it through.

So, I’d like to apologize to whoever posted a comment on my site that didn’t actually get through.  I just didn’t realize the comment was posted until it was too late.  Hopefully this won’t happen in the future.

Kirk out.

PowerShell Challenge: Comparing PSSnapin objects

When working on my Integrated PowerShell Help PowerPack for PowerGUI the other day I came across something that I haven’t quite figured out yet, so I thought I’d share it here and see if anyone else can contribute.  Here’s the challenge:

(Get-PSSnapin snapinName) -eq (Get-PSSnapin -Registered snapinName)

Assuming that you’ve already added a snapin called snapinName to your PowerShell session using Add-PSSnapin snapinName, why doesn’t this expression return True?

Here are some of the reasons why it seems to me like this should return True:

  1. In both cases, you’re retrieving an object of type System.Management.Automation.PSSnapInInfo.
  2. If you pipe either side of the comparison into Select-Object and specify that you want to see all properties the output will be identical ( | Select-Object -Property *).
  3. If you pipe either side of the comparison into Format-Custom, the output will be identical.
  4. The PowerShell snapin is the same on both sides of the comparison.
  5. In one case you’re asking for a specific PowerShell snapin by name that has been added to the current PowerShell session and in the other case you’re asking for a specific registered PowerShell snapin by name; in both cases, you’re still asking for the same PowerShell snapin.

The only difference I was able to find between these two objects was that the hash code returned from the GetHashCode method was different.

If you know why this test for equality fails and want to share that knowledge, I’d appreciate it.

Kirk out. 

P.S. There is something else odd about PowerShell snapins that I encountered that is related to this.  If you call Add-PSSnapin sNaPiNnAmE, PowerShell adds the snapin and stores it with the name just as you entered it (in this case, as sNaPiNnAmE).  Why?  PowerShell script isn’t case sensitive so the script can find the snapin just fine, but it doesn’t seem logical to add it to the PowerShell session using the same case you used in your script to add it when it could easily retrieve the name from the snapin object itself.  This isn’t really important, but it is just something else I haven’t resolved that has been bothering me.

Technorati Tags: , , ,

Essential PowerShell: Understanding foreach

Of all of the statements and commands available in PowerShell, there is one in particular that I found causes more confusion than others for newcomers to the language — foreach.  In PowerShell, foreach is both a statement and an alias to the ForEach-Object cmdlet.  This means that you can use it as a statement like this:

foreach ($command in Get-Command -CommandType All) { $command } 

 or as an alias like this:

Get-Command -CommandType All | foreach { $_ }

While you might think that both of these examples do exactly the same thing, they do not.  Both examples will iterate through a collection of objects and execute the internal script block once for each object.  In this case, both examples are simply outputting the objects in the internal script.  Their output will be the same, but how they go about getting that output is different.  It is important to understand these differences and the implications that they have on performance and memory when writing scripts using PowerShell.  Let’s talk about the memory implications first.

The foreach statement does not use pipelining.  Instead, the right-hand side of the in operator is evaluated to completion before anything else is done.  For our example above, the Get-Command cmdlet is called and the results are completely loaded into memory before the interior script block is executed.  This means you have to have enough memory to store all of the objects when you run the script.  This usually isn’t a problem but as my friend Dmitry Sotnikov points out on his blog, in some cases it can definitely be an issue.

In contrast, the foreach alias, or ForEach-Object cmdlet, does use pipelining.  When the second example is used, Get-Command is called and it starts to return the commands one at a time.  As each object is returned out of the Get-Command cmdlet, it is sent into the pipeline and execution continues in the next section of the pipeline.  In this case, the foreach alias gets executed and the object is run through the process script block of ForEach-Object.  Once the process script block completes, the object is discarded and the next object is returned from Get-Command.  Since only one object is passing through the pipeline at a time, memory usage is minimal.

This would seem to indicate that script authors should always prefer the foreach alias, or ForEach-Object cmdlet, over the foreach statement, but according to Bruce Payette, author of PowerShell in Action and development lead for PowerShell, foreach can perform faster than ForEach-Object in some cases.  He states, “in the bulk-read case, however, there are some optimizations that the foreach statement does that allow it to perform significantly faster than the ForEach-Object cmdlet”.  If that’s the case, how does a script author decide which is the right command for the job?  How will those optimizations influence a decision to choose the foreach statement over the foreach alias?  How much faster is significantly faster?  Let’s take a closer look at the performance and what considerations need to be made.

I ran a test on my local machine to compare the performance of the two examples I listed above.  For this test I used the Get-Date cmdlet to retrieve the date before the example script started and after the example script completed and then I took the difference of these dates to determine how much time had elapsed during the script.  I also ran this test through 10 iterations for each example and I discarded the highest and lowest elapsed times.  I then took the averages of the remaining 8 iterations and compared them.  The results confirmed what Bruce Payette said.  The average runtime for the foreach statement example was 13.9 seconds and the average runtime for the foreach alias example was 15.9 seconds.  This shows how the internal optimizations in the foreach statement improve performance when compared to the foreach alias.

So, it seems pretty simple.  Use the foreach statement when you either already have the array of objects that you want to process or when your collection of objects will be small enough that it can be loaded into memory all at once, right?  Well that depends on what aspect of performance is most important to you.

One of the many beautiful things about PowerShell is the support for the pipeline and how objects are passed through (and out of) the pipeline one at a time.  If you’re working with an application that is displaying the data objects that are output through the pipeline of a script, such as PowerGUI, you may be more concerned with the performance rate at which those data objects are output through the pipeline so that you can display them more quickly then the overall amount of time required to output all objects.  Whatever portion of the 13.9 seconds were used to load the objects into the collection may seem like an eternity to wait until the first object is displayed on the screen when you can see thousands of objects displayed iteratively over 15.9 seconds.  Perspective is everything when you’re talking about performance.

Hopefully this will lift some of the confusion that you might otherwise face when using foreach in your scripts!

Kirk out.

P.S. This is the first of two articles discussing foreach in PowerShell.  After reading this article I recommend you read the second part as well, entitled “Essential PowerShell: Understanding foreach (addendum)“.

Technorati Tags: , , ,

And then there was PowerGUI

As alluded to in my last post, there were a number of really powerful products already available (in beta at least) when I started using PowerShell.  One of those products in particular has been a big source of inspiration to my becoming more involved in PowerShell and the PowerShell Community.

PowerGUI is a wonderful little free product that wraps an extendible user interface around a PowerShell host.  You can download it here, no registration required.  This product allows users to extend an administrative console with their own PowerShell scripts, allowing them to build a rich, customized user experience with very little cost and minimal if any user interface code.  Scripts are stored associated to nodes that appear in a tree and associated to links and actions that appear next to a data grid.  Out of the box it comes with a few scripts pre-loaded into nodes, links and actions.  One example is the Services node which has a script associated with it that will get all services on the local machine.  All PowerShell scripts that are available through the PowerGUI user interface can be viewed and modified at any time.

Additional nodes, links and actions may be added by any user through the PowerGUI user interface, or they may be added by importing one of the many free PowerPacks that are available.  A PowerPack is a collection of PowerShell scripts that are made available to end users through extensions to the PowerGUI user interface (nodes, links and actions).  Any PowerGUI user can extend their PowerGUI interface further by downloading PowerPacks from the library on the popular PowerGUI Community site.  Once downloaded, users simply have to import the PowerPacks into the PowerGUI console.

If you’re new to PowerGUI or PowerShell, I recommend you download the Integrated PowerShell Help PowerPack.  I designed this PowerPack to facilitate getting at some of the rich help information that is inherent in PowerShell.  One of the great features of PowerShell is that its help information is readily available through PowerShell scripts; the only trouble is that you have to know what cmdlets to call in your script to get at that help information.  This PowerPack helps alleviate some of that pain by allowing users to find the help information in a user interface and by allowing them to see the PowerShell script that was used to get the information.

The PowerGUI Community is fairly active, with more and more new users showing up in the forums all the time.  It has proven to be a great place to ask questions or notify the PowerGUI team about any defects or enhancement requests.  The PowerGUI team is very responsive to posts on the forums, and many features in the current version of the product are there because users requested them through the PowerGUI site.  I’m so happy with the features that have been added to the product so far that I can’t wait to see what is coming next.  The forums are freely readable, but if you wish to post anything you must first register.

In a nutshell, PowerGUI is a great little program that belongs in the toolbox of anyone who works with PowerShell, and the
PowerGUI Community is a great source of information related to PowerGUI and PowerShell.  I highly recommend them both!

Kirk out.

Technorati Tags: , , , ,

And along came PowerShell

Hello, my name is Kirk Munro and I’m a Poshoholic.

And I’m not talking in a Victoria Beckham kind of way either.  I guess it all started about 6 months ago.  Before that I wasn’t really that attached to any technology.  My evenings and weekends were free to do with whatever I would choose.  I would go to bed on time.  I’d watch more TV.

And along came PowerShell.

It wasn’t all that sudden, really.  I had already experimented with it when it was in beta and thought I knew what it was all about.  But shortly after it was released I finally decided to take a more serious look at it.  And then I started to really experience first-hand how PowerShell is rich.  Really rich.  And that there are really powerful tools for it too.  And a community that is growing very, very fast.  And it is just so rich.

So I’m finally starting something that has been on my todo list for a long time.  My own professional blog.  Until recently, I just hadn’t found the right inspiration for it.  But PoSh and the growing community around it gave me that inspiration.  This technology is just amazing, and with the community surrounding it growing stronger all the time this is likely going to be a lot of fun.

I hope you enjoy it.  I think I will.

Kirk out.

Technorati Tags: , ,