PowerShell Cookbook

Twitter Updates

    follow me on Twitter

    Search

    Categories

     

    On this page

    Supporting Additional View Details

    Archive

    Blogroll

    Disclaimer
    I work for Microsoft.

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    RSS 2.0 | Atom 1.0 | CDF

    Send mail to the author(s) E-mail

    Total Posts: 235
    This Year: 12
    This Month: 0
    This Week: 0
    Comments: 634

    Sign In

     Monday, October 20, 2008
    Monday, October 20, 2008 4:37:20 PM (Pacific Daylight Time, UTC-07:00) ( )

    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.

    Comments [0] | | #