Archives for the Month of October, 2008

Introduction to PowerShell Presentation

Once you’ve been using PowerShell for awhile, it’s natural to want to spread the word. We frequently get questions asking for a standard “Introduction to PowerShell” slide deck, but haven’t really had one to share. The problem is that they tend to be pretty customized to the audience – even a “standard intro talk” becomes much more engaging when you target it to a specific audience.

However, those customizations tend to be centered around specific themes, so I’ve reduced a recent presentation to its core and attached it here. This presentation is demo-heavy. Talk all you want about objects, but it doesn’t really click until they see it in action.

Link: Introduction To PowerShell.zip

To run the demos, this zip file includes a version of Jeffrey Snover’s Start-Demo script. This script is pure Presentation Zen. By automating your keystrokes (yet submitting them to the real PowerShell console,) it lets you demonstrate the wonder of PowerShell without torturing your users with lame attempts to type and talk and backspace all at the same time.

.\Start-Demo .\Demo-Discovery.ps1

The Graphical PowerShell demo is not scripted -- the high points I like to hit are:

  • UNICODE. PowerShell has always been Unicode-friendly, but the console window is less so.
    We literally had Exchange administrators in Japan having to write scripts in Notepad, and then run those scripts in order to manage some mailboxes. I usually create a directory with a Unicode name, do a dir. Create a file within it (with a Unicode name,) and do a dir. Set the content (with Unicode text) and then get the content (which shows the Unicode text.) I like to use “PowerShell Rocks!” flipped from http://www.flipmytext.com/
  • Syntax highlighting and Tab Completion
  • Tabs and Free-sizing of the window. It seems like a small thing, but it’s the most common complaint about the console window.

Also, the font slider at the bottom right lets you enlarge all fonts to become demo-friendly.

Supporting Additional View Details

A question came up on an internal discussion list today about how to let a cmdlet support both simple and detailed views. For example, a –Detailed flag to tell the cmdlet to emit additional information during the request.

The original approach was to do all of this filtering inside of the cmdlet. When –Details is not specified, run through some additional code to remove the extraneous properties.

The goal is noble, but the implementation decision is misguided.

The correct approach here is to have your cmdlet ALWAYS output all of the information. Your default display should have the most important properties, but users shouldn’t have to specify the –Details switch to get access to more.

Compare to System.Diagnostics.Process, a property-rich class emitted by the Get-Process command:

PS C:\Windows\System32> $powershell = Get-Process -Id $pid
PS C:\Windows\System32> $powershell

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    445       9    36688      38156   175     0.78   9828 powershell

If the user wants to view additional details:

PS C:\Windows\System32> $powershell | format-list *
__NounName                 : Process
Name                       : powershell
Handles                    : 445
VM                         : 183631872
WS                         : 39071744
PM                         : 37568512
NPM                        : 9500
(...)

But they can still access specific details if they want:

PS C:\Windows\System32> $powershell.FileVersion
6.1.6930.0 (fbl_srv_powershell(leeholm).071018-1329)

If you have different views of the information you want to surface, our Formatting and Output system fully supports this through formatting extensions and View Names.

In some cases, different views really are a core scenario for the cmdlet. For example, WMI returns an enormous amount of data for nearly everything you request. However, you care about different properties for processes than you do for services, logical disks, etc. In that case, you can add a synthetic type name to the objects you return that indicate the view. Then, write types or formatting sections that apply directly to the synthetic type:

PS >$disk = (Get-WmiObject Win32_LogicalDisk)[0]
PS >$disk.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ManagementObject                         System.Management.ManagementBaseObject

PS >$disk.PsObject.TypeNames
System.Management.ManagementObject#root\cimv2\Win32_LogicalDisk
System.Management.ManagementObject
System.Management.ManagementBaseObject
System.ComponentModel.Component
System.MarshalByRefObject
System.Object

and the corresponding type definition:

<Type>
    <Name>System.Management.ManagementObject#root\cimv2\Win32_LogicalDisk</Name>
    <Members>
        <PropertySet>
            <Name>PSStatus</Name>
            <ReferencedProperties>
                <Name>Status</Name>
                <Name>Availability</Name>
                <Name>DeviceID</Name>
                <Name>StatusInfo</Name>
            </ReferencedProperties>
        </PropertySet>
        <MemberSet>
            <Name>PSStandardMembers</Name>
            <Members>
                <PropertySet>
                    <Name>DefaultDisplayPropertySet</Name>
                    <ReferencedProperties>
                        <Name>DeviceID</Name>
                        <Name>DriveType</Name>
                        <Name>ProviderName</Name>
                        <Name>FreeSpace</Name>
  
                      <Name>Size</Name>
                        <Name>VolumeName</Name>
                    </ReferencedProperties>
                </PropertySet>
            </Members>
        </MemberSet>
    </Members>
</Type>

Use the PsObject.TypeNames.Add() method to add custom type names to your output object.

The core tenet here is minimizing the amount of back-tracking the user needs to do. When they realize they need additional data, don’t make them re-run the command, specify –Details, and start over. If your cmdlet always emits the information (even if it is hidden by a view,) they can still access it when they want.