Windows PowerShell: Cereal or Serial?

Serializing can help when exporting or retrieving objects with Windows PowerShell.

Don Jones

When I run classes on Windows PowerShell, I’m constantly telling my students to pipe objects to Get-Member:

Get-Process | Get-Member

Get-Member, or GM for short, is designed to use a Microsoft .NET Framework feature called reflection. This feature displays information about an object, including its official name, properties, methods and so on. This cmdlet is a much easier way to quickly see what an object can do than digging around in a search engine or poring through the MSDN Library Web site.

Sometimes, though, when students try to execute this cmdlet, they’ll see something like this from Get-Member:

TypeName: Deserialized.System.Diagnostics.Process

OK, I know what a Process is, but a de-serialized process? Further investigation of the Get-Member output also reveals that, unlike normal processes that have methods to stop the process and take other actions, these de-serialized processes don’t seem to have any methods, meaning you can’t make them take any action. What’s up with that?

How Objects Become Cereal … er, Serialized

In Windows, objects are functioning bits of software. A process is literally a software application. A process object provides properties that describe some attributes of a process, like its name, memory utilization and so forth; the object may also have methods to trigger actions like stopping, refreshing and so on.

Objects are great when they’re on your computer, but there’s no real practical way to transmit an entire object across a network. Serializing is a way to create a text representation of an object, usually in XML. Figure 1 shows process objects that have been serialized into XML.

Essentially, the serializing technique takes a snapshot of the object’s properties, encodes them into a structured XML file, and then transmits that file across the network. At this point, the XML file is essentially just a text file. There’s no longer a direct connection between the actual running processes and that XML file. The file is a point-in-time view of the properties of the transmitted object.

Figure 1 The XML file will serialize the process objects

Figure 1 The XML file will serialize the process objects.

Serialization doesn’t preserve an object’s methods. There’s no way to go back to the original object and tell it to execute the method. When the shell needs to read that serialized object, it deserializes it. It does this by reading the XML text and constructing something that looks very much like the original object—without all of its methods, of course.

Common Places for Serial Objects

Windows PowerShell v2 uses serialization in two common places:

  • When you export objects to an XML format using Export-CliXML
  • When you retrieve objects from a remote computer using Windows PowerShell remoting

For example, this command will retrieve running processes from a remote computer, sort them on virtual memory utilization, and display the first 10:

invoke-command { ps } -computer server-r2 | sort vm -desc | select -first 10

You could also have all the sorting and selecting occur on the remote computer, which has the benefit of transmitting fewer serialized objects across the network:

invoke-command { ps | sort vm -desc | select -first 10 } -computer server-r2

The point is that the objects coming across the network are no longer real processes. They’ve been put into XML format. You couldn’t grab one of those processes and tell it to stop itself, because there’s no connection between what you have on your local computer and what’s running on the remote computer.

Serializing can also be useful for storing object information. For example, suppose you export all your services’ configurations to an XML file:

get-wmiobject win32_service | export-clixml baseline.xml

You could then use that snapshot to compare the server’s configuration in the future. This would alert you to any configuration changes that you may have made, whether inadvertently or on purpose.

This command compares the current service objects to the ones in your snapshot:

compare-object (get-wmiobject win32_service) (import-clixml baseline.xml)

In this instance, the fact that deserialized objects don’t have methods isn’t important. It’s the properties that contain all of the configuration information—like start mode, login account and so on.

Be Careful with Cerealized … er, Serialized Objects

Serialization can be a problem, however, when you need access to an object’s methods. For example, this command works fine on your local computer (and will reboot it, so don’t run it unless you’re ready for that):

Get-WmiObject Win32_OperatingSystem | ForEach-Object { $_.Reboot() }

The following command won’t work, though:

Invoke-Command { Get-WmiObject Win32_OperatingSystem } –computer Server-R2 | ForEach-Object { $_.Reboot() }

That’s because the result of Invoke-Command is a deserialized object with no methods. We can’t execute the Reboot method. We could, however, do this:

Invoke-Command { Get-WmiObject Win32_OperatingSystem | ForEach-Object { $_.Reboot() }} –computer Server-R2

We’re now invoking the Reboot method on the remote computer, before the object is serialized and loses its methods. So whenever serialization seems to be creating a problem, there’s usually a work-around. You just have to be aware of when the serialization is happening.

Don Jones

Don Jones* is a founder of Concentrated Technology, and answers questions about Windows PowerShell and other technologies at ConcentratedTech.com. He’s also an author for Nexus.Realtimepublishers.com, which makes many of his books available as free electronic editions through his web site.*