Thomas Lee (tfl@psp.co.uk) MCT PowerShell MVP FORMATTING WITH POWERSHELL MCT PowerShell MVP Worked with, trained and written about PowerShell for years! SME on 6434 and TR on 10325 official MOC classes I have 25 copies of PowerShell Plus http://www.idera.com/Products/PowerShell/PowerShell- Plus/ or http://tinyurl.com/psplus To win: You need to email me with a code word. 2. Email me at tfl@psp.co.uk 3. The code word will be at the end of the presentation 1. Know a bit (or more) about PowerShell At least to the level of the earlier Summit session! You know what a cmdlet is, what the pipeline does and what objects are And you want to do more with formatting If you want to type-along with me, feel free! Formatting by default Formatting using Format-table, Format-List Using .NET format Strings .ToString() Formatting using Hash Tables Formatting XML Other output mechanisms Some thoughts on style etc PowerShell formats output by default Useful for simple queries Formatting is controlled by Format.PS1XML files Seven are installed by default LS $PSHOME\*.Format.PS1.XML You can You can edit built in Format.PS1XML files - but don’t… Instead, add new ones and ‘install’ in Profile The default formatting process Cmdlet or Pipeline Out-Default Format-Table or Format-List Formatted Output On Console User Defined Formatting Cmdlet or Pipeline Format-Table or Format-List Out-Default Formatted Output On Console Other Options Out-Gridview Cmdlet or Pipeline Cmdlets Text, CSV, XML Cmdlets take objects from pipeline – create table/list Default contents and ‘shape’ determined by .ps1xml You can override defaults, for example: GWMI win32_ComputerSystem | fl name,model Can also take a hash table for precise format control Used to print a single property as a table The Format-* cmdlets format objects Om the pipeline or via –Inputobject parameter You can adjust the details of how you want your data to appear using the cmdlets, hash tables, format strings, etc They produce format objects The Out-* cmdlets take format objects and output it to the console (and elsewhere) Format-Table -Autosize Waits till ALL objects are ready before formatting and autosizes the width of each column -HidetableHeaders Hides table headers Format-List and Format-Table -GroupBy But you need to sort first Objects in the pipeline are sent to Out-Default Out-Default looks at the objects in the pipeline If formatting instructions – send it to Out-Host If objects - send to Format-List or Format-Table Out-Default looks in .PS1XML for guidance Select 1st view for guidance Five or less properties – call Format-Table Otherwise call Format-List This creates format objects Sent to Out-Default and then to the console You can get basic output from PoweShell using default formatting You can see more/different using Format-table/list directly FL/FT typically used at the end of a pipeline But PowerShell is built on .NET Lets leverage .NET formatting Composite String – with placeholders "There are{0} ps1 files" –f (ls C:\foo\*.ps1).count Placeholder Syntax {index[,alignment]{:formatstring}] Simple placeholder examples {0} {0,20} {0,-20:n} Use these along with the –f operator .NET formats values into the composite string! Fixed decimal point $a=123.4567898 "The Number is: {0:#.000}" –f $a The Number is: 123.456 Currency $a=123456.789123 "{0:c2}" –f $a £123,456.79 Phone Number $a=4255551212 "{0:(###) ###-####}" -f $a (425) 555-1212 All types have a .ToString() method Inherited from [Object] Base types have power over how to format Pass a format string to .ToString() to control formatting Example $i = 23.123456 $i.tostring("N2") 23.12 Format output for a single related set of values Number of files Number of files and their total size Also use it to format one line in a table Foreach ($file in $files) {display some aspect(s) of each file} .NET Formatting string used in Composite format string ToString() Hash Tables (later in this talk) Numeric format strings http://msdn.microsoft.com/en-us/library/427bttx3(VS.71).aspx Date and time format strings http://msdn.microsoft.com/en-us/library/97x6twsz(VS.71).aspx Enumeration format strings http://msdn.microsoft.com/en-us/library/c3s1ez6e(VS.71).aspx Simple Formatting DEMO 1 Using FT/FL, you can create a ‘calculated field’ Field defined by a Hash Table with pre-defined key names: (or Label) - <string> Expression - <string> or <script block> FormatString - <string> Width <int32> Alignment - value can be "Left", "Center", Name or "Right") Send FT/FL hash table vs a property name $x1=@{label="Process Name"; Expression={$_.name}; alignment="right"} $x2=@{label="CPU Used"; Expression={$_.CPU}; FormatString="N3"} Get-Process notepad | Format-Table $x1,$x2 -auto $x1=@{label="Process Name";Expression={$_.name}; alignment="right"} $x2=@{label="CPU Used"; Expression={$_.CPU};FormatString="N3"} Get-Process | Format-Table $x1,$x2 –autosize $x3=@{label="Process Name"; Expression={$_.name}} Get-Process | Format-List $x3,$x2 Give FT/FL better column/table headers Sometimes property name is ugly/unhelpful Display a calculated value Covert a number into gb/mb etc Expression = {$_.Length/1GB} Coerce field into to nicer format easily XML Import-CliXML Export-CliXML ConvertTo-XML CSV Export-CSV (and Import-CSV) Useful for interop with XML Applications Uses WPF You need latest .NET Framework Creates sortable list in a separate window with criteria to help limit output Out-GridView (and PowerShell ISE) need .NET 3.51 The rest of PowerShell requires .NET 2.0 Out-Gridview and ISE use WPF By default, Out-Gridview displays same columns as FT Clone the object first to see all object properties Get-Process | Select-Object * | Out-Gridview Hash tables and FT/FL DEMO 2 Seen default formatting Used FT/FL and hash tables Formatted using .NET So let’s do create custom XML Two types of ps1xml Define/update types - *.types.ps1xml Define/update formatting - *.format.ps1xml Default Format XML shipped with PowerShell Apps , OS additions, modules add to this default set Stored in $PSHOME DO NOT EDIT THESE FILES! They are signed – editing breaks that! Copy and edit them instead Don’t like the way PowerShell formats a type? Develop your own display XML PowerShell ships with 7 format.ps1xml files You can write your own Define four views: table, list, wide, and complex Do NOT edit existing files – make a copy and edit it Run Update-FormatData to add new view Add this to $profile to persist the change <Name> Identifies the name of the view. <ViewSelectedBy> Specifies the object type or types to which the view applies. <GroupBy> Specifies how items in the view should be combined in groups. <TableControl> <ListControl> <WideControl> <ComplexControl> Contain the tags that specify how each item is displayed. Add-Type @' public class aeroplane { public string Model = public int InFleet public int Range = public int Pax = } '@ "Boeing 737"; = 12; 2400; 135; But what about the display? Use FormatData.ps1xml <Configuration> <ViewDefinitions> <View> <name>Airplane</name> <TableControl>…</TableControl> </View> <View> <name>Airplane</name> <ListControl>…</ListControl> </View> </ViewDefinitions></Configuration> Saved as Aeroplane.formatdata.ps1xml Imported as needed/when needed <TableControl> <TableHeaders> <TableColumnHeader> <label>Passengers</label><width>12</width> </TableColumnHeader> … </TableHeaders> <TableRowEntries> <TableRowEntry> <tableColumnItem><PropertyName>Pax</PropertyName</tablecolumnitem> </TableRowEntry> </TableRowEntries> </TableControl> … <ListControl> <ListEntries> <ListEntry> <ListItems> <ListItem> <PropertyName>Model</PropertyName> </ListItem> <ListItems> <ListEntry> </ListEntries> </Listcontrol> … Save XML to C Update-FormatData c:\foo\aeroplane.format.ps1xml Then: $Object = new-object aeroplane $object $object | fl You can also extend existing types or add new ones Create XML file describing your addition Use Update-TypeData to incorporate it Persist the change by updating $Profile <Types> <Type> <Name>System.Object</Name> <Members> <ScriptMethod> <Name>MSDN</Name> <Script> if (($global:MSDNViewer -eq $null) -or ($global:MSDNViewer.HWND -eq $null)) { $global:MSDNViewer = new-object -ComObject InterNetExplorer.Application} $Uri = "http://msdn2.microsoft.com/library/" + $this.GetType().FullName + ".ASPX" $global:MSDNViewer.Navigate2($Uri) $global:MSDNViewer.Visible = $TRUE </Script> </ScriptMethod> </Members> </Type> </Types> Create the XML On your workstation XCOPY during logon script? Store it somewhere useful C:\foo Somewhere else?? Add the type/format information to your $Profile Update-TypeData -Path <path> Update-FormatData –Path <path> Formatting can be simple or complex Lots of alternatives – have it your way Keep it simple and extend to meet your needs I have free copies of PowerShell Pro Idera’s PowerShell Development Tool The first 25 folks to email me will get a link to download the software (and a license). I gave you the email address at the start of this presentation The codeword is “POWERSHELLISAWESOME!” The first 25 to mail that code word to the address I gave earlier will win their prize! Adding .MSDN() to types http://blogs.msdn.com/powershell/archive/2006/06/24/644987 Formatting - see TFL’s articles on formatting http://tfl09.blogspot.com/2010/02/formatting-with- powershell.html .NET Formatting http://msdn.microsoft.com/en-us/library/txafckwd(VS.71).aspx Thomas Lee’s Blogs/PowerShell site http://tfl09.blogspot.com http://pshscripts.blogspot.com http://www.reskit.net/psmc THE END