Summary: Windows PowerShell MVPs, Don Jones, Richard Siddaway, and Jeffrey Hicks share excerpts from their new book.
Microsoft Scripting Guy, Ed Wilson, is here. This week we will not have our usual PowerTip. Instead we have excerpts from seven books from Manning Press. In addition, each blog will have a special code for 50% off the book being excerpted that day. Remember that the code is valid only for the day the excerpt is posted. The coupon code is also valid for a second book from the Manning collection.
Today, the excerpt is from PowerShell in Depth
By Don Jones, Richard Siddaway, and Jeffery Hicks
If you use Windows PowerShell, the Help, format, and type files are XML. The new “cmdlet over objects” functionality in Windows PowerShell 3.0 is based on XML. The HTML- and XML-related functionality hasn’t had any major changes in Windows PowerShell 3.0. In this excerpt from PowerShell in Depth, the authors cover several capabilities and provide some concise examples of how you might want to use them.
Windows PowerShell includes some great capabilities for working with two common forms of structured data: HTML and XML. Why is this important? Because HTML is a great way to produce professional-looking reports and you can use XML in so many places within your environment. The XML abilities in Windows PowerShell are no less amazing than its HTML abilities. We’ll cover a couple of specific use cases and the commands and techniques that help you accomplish each in this tip.
Using XML to persist data
One common use of XML is to preserve complex, hierarchical data in a simple, text-based format that’s easily transmitted across networks, copied as files, and so forth. XML’s other advantage is that it can be read by humans if required. Objects (PowerShell’s main form of command output), are one common kind of complex hierarchical data, and a pair of Windows PowerShell cmdlets can help convert objects to and from XML. This process is called serializing (converting objects to XML) and deserializing (converting XML back into objects). It’s almost exactly what happens in Windows PowerShell remoting when objects need to be transmitted over the network. Here’s a quick example:
PS C:\> Get-Process | Export-Clixml proc_baseline.xml
This code creates a static, text-based representation of the processes currently running on the computer. The Export-Clixml cmdlet produces XML that’s specifically designed to be read back in by PowerShell.
Note The Export verb, unlike the ConvertTo verb, combines the acts of converting the objects into another data format and writing them to a file.
PS C:\> Import-Clixml .\proc_baseline.xml | sort -property pm -Descending |
select -first 10
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
783 77 336420 285772 819 43.69 2204 powershell
544 41 196500 166980 652 13.41 2660 powershell
348 24 91156 39032 600 1.28 92 wsmprovhost
186 18 52024 35472 170 5.56 716 dwm
329 28 24628 24844 213 0.30 2316 iexplore
311 26 24276 22308 213 0.30 108 iexplore
210 14 20628 26228 69 5.95 1828 WmiPrvSE
1327 41 19608 33164 126 49.45 764 svchost
398 15 19164 21120 56 3.95 728 svchost
722 47 17992 23080 1394 13.45 924 svchost
The previous example demonstrates that the objects are imported from XML and placed, as objects, into the pipeline, where they can again be sorted, selected, filtered, and so forth. These deserialized objects are static, and their methods have been removed because they’re no longer “live” objects against which actions can be taken.
But because XML captures a hierarchy of object data, it’s an excellent tool for capturing complex objects. We recommend using the CliXML format as an intermediary rather than JSON.
Reading arbitrary XML data
You might also have a need to work with XML that comes from other sources. For example, the following is a brief XML file that contains information about two computers. You’ll use it in a running example:
<computers>
<computer name='WIN8' />
<computer name='LOCALHOST' />
</computers>
Warning Unlike most of Windows PowerShell, XML tags are case sensitive. Using <computers> and </Computers> won’t work. Be careful if you’re retyping this example to get it exactly as shown here.
The Get-Content cmdlet can read the plain-text content of this XML file, but it will treat it as plain text. By casting the result as the special [xml] data type, you can force Windows PowerShell to parse the XML into a data structure. You’ll store the result in a variable to allow you to work with it and display the contents of the variable:
PS C:\> [xml]$xml = Get-Content .\inventory.xml
PS C:\> $xml
computers
---------
computers
You can see that the variable contains the top-level XML element, the <computers> tag. That top-level element has become a property. Now you can start exploring the object hierarchy:
PS C:\> $xml.computers
computer
--------
{WIN8, LOCALHOST}
PS C:\> $xml.computers.computer[0]
name
----
WIN8
PS C:\> $xml.computers.computer[1]
name
----
LOCALHOST
You can see how it’s easy to explore the object model from this point.
Creating XML data and files
But reading XML data is only half the fun. Windows PowerShell also lets you create XML files that can be used outside of Windows PowerShell with the ConvertTo-XML cmdlet:
PS C:\> $xml=Get-WmiObject Win32_Volume | ConvertTo-Xml
PS C:\> $xml
xml Objects
--- -------
version="1.0" Objects
PS C:\> $xml.objects.object[0]
Type Property
---- --------
System.Management.ManagementObject {PSComputerName, __GENUS, __CLAS...
PS C:\> $xml.GetType().Name
XmlDocument
You haven’t created an XML file, but only an XML representation of the Get-WmiObject result. But assuming you have XML experience and knowledge, you could explore or modify the XML document.
When you’re ready to save the XML document to a file, invoke the Save() method. You should specify the full path and filename:
PS C:\> $xml.Save("c:\work\volume.xml")
Unlike ConvertTo-HTML, you can’t pipe to Out-File and expect an XML document. You need to take this manual step, but you can use a shortcut like the following to do it all in one step:
(Get-WmiObject Win32_Volume | ConvertTo-Xml).Save("c:\work\volume.xml")
With so much of the world’s data in XML and HTML, being able to work those formats can be handy. Windows PowerShell provides a variety of capabilities that should be able to address most common situations. Obviously, the more knowledge you have of those formats and how they’re used, the more effective you’ll be with Windows PowerShell’s ability to handle them.
Here is the code for the discount offer today at www.manning.com: scriptw1
Valid for 50% off PowerShell in Depth and SQL Server DMVs in Action
Offer valid from April 1, 2013 12:01 AM until April 2 midnight (EST)
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy