PowerShell’s Object Orientedness

This article was authored by Don Jones and is taken from the SAPIEN Knowledge Base at www.sapien.com/support.asp. Select the “Windows PowerShell” category for this and more information on Windows PowerShell’s inner workings.

 

Understanding PowerShell?s object-orientation can be difficult because there?s no real way to see the objects in action. The first step in understanding, however, is to realize that when you?re using PowerShell, you?re not really using PowerShell.

 

That deserves some explanation. Normally, ?using PowerShell? means running Powershell.exe, located in \Windows\System32\WindowsPowerShell\v1.0. However, Powershell.exe is just a ?hosting application;? it?s not PowerShell itself. Seeing how the executable is only about 320KB, that shouldn?t come as a surprise! The actual guts of PowerShell are contained in a set of .NET Framework-based DLLs. When you run Powershell.exe, it loads up those DLLs and ?hosts? them. Other applications can ?host? the PowerShell ?engine,? as well, including the Exchange Server 2007 Management Console.

 

So the object-orientation of PowerShell occurs in the ?engine,? which has all of the shell?s functionality. When the engine finishing doing something with an object, it passes the resulting object (or objects) to the hosting application. When that application is a management console, the objects might be displayed, or ?rendered,? as a set of icons or something. In Powershell.exe, however, which is a text-based command-line host, the objects are rendered as text that you can read.

 

For example, try running this:

PS C:\> gwmi win32_operatingsystem

 

 

SystemDirectory : C:\WINDOWS\system32

Organization    : SAPIEN Technologies, Inc.

BuildNumber     : 2600

RegisteredUser  : Don Jones

SerialNumber    : XXXXX-XXX-XXXXXX-XXXXX

Version         : 5.1.2600

 This command, Get-WMIObject (aliased as gwmi) retrieves the instance of the WMI Win32_OperatingSystem class. Looking at the output here, you might assume that these six pieces of information are all that Win32_OperatingSystem contains. Not so: In fact, what happened is that the PowerShell engine retrieved the entire Win32_OperatingSystem object for me? it?s just that, when the Powershell.exe host rendered the object as text, it selected a subset of the available properties. I can prove it:

PS C:\> $wmi = gwmi win32_operatingsystem

PS C:\> $wmi.servicepackmajorversion

2

PS C:\>

 I did the same thing here, only I assigned the Win32_OperatingSystem object to a variable, $wmi. As you can see, this let me access an additional property, ServicePackMajorVersion, which wasn?t in the list that the host rendered the first time. In fact, by piping the $wmi variable ? which contains an object, remember ? to the Get-Member cmdlet, I can see all of its available properties and methods, most of which weren?t rendered by the host the first time I retrieved this object.

 

In fact, ?piping? is perhaps the most important reason to understand PowerShell?s object-oriented nature. When you pipe one cmdlet to another, or a variable to a cmdlet, or in fact pipe anything to anything else, what you?re doing is passing along objects. Because piping takes place entirely within the shell?s engine, it?s just moving objects from one place to another. Once the engine is done doing whatever you told it, the resulting object (or objects) are passed to the host, which renders them in whatever way it wants to; in the case of the Powershell.exe host, that means turning the objects into text, usually by displaying selected properties of the objects.

 

So how does the host decide what to display when it turns an object into text? It has some choices. First, remember that PowerShell is based on .NET, so all of these objects are really just .NET Framework classes. Many .NET Framework classes have a built-in method called ToString(), which causes the object to produce a text rendition of itself. Whoever created the .NET class ? a Microsoft programmer, in other words ? got to decide what the text rendition would look like. So PowerShell could simply call an object?s ToString() method and display whatever text was produced.

 

But PowerShell?s a bit smarter than that. It also uses a set of formatting XML files, located in the same folder as PowerShell.exe. For example, one such file is filesystem.format.ps1xml. Open this file in Notepad or PrimalScript and scroll down a bit until you find the ?View Definitions.? Here, several ?views? are defined, and each view is essentially a set of instructions for rendering a particular type of object into text. This particular file handles objects related to the file system, and defines views such as a directory listing. After all, when you run the Dir command ? which is just an alias to the Get-ChildItem cmdlet ? what the PowerShell engine returns is a list of objects ? some file objects, perhaps, and some folder objects. The Powershell.exe host needs to render those into text, and the filesystem.form.ps1xml file tells it how to do so. Let?s look at how this file breaks down:

 

At the top, notice a SelectionSet named FileSystemTypes. This SelectionSet includes four .NET classes: System.IO.DirectoryInfo, System.IO.FileInfo, and so forth. So, anytime these objects are passed to the Powershell.exe host, it?ll include them in this SelectionSet.

 

A bit further down, I see a view named Children. This view defines itself ? using the ViewSelectedBy tag ? for the FIleSystemTypes SelectionSet. In other words, objects within that SelectionSet will be displayed using this view. The view groups objects by the property PSParentPath. It displays objects in a table, with columns labeled Mode, LastWriteTime, and Length (this is easier to see if you open the file and follow along). For the table rows, it says that the ?Mode? column should contain each object?s ?Mode? property. The ?LastWriteTime? columns contains a formatted version of the object?s ?LastWriteTime? property, and so forth.

 

The result? Running Dir does in fact display those columns:

PS C:\> dir

 

 

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\

 

 

Mode                LastWriteTime     Length Name

—-                ————-     —— —-

d—-          1/9/2005  10:16 PM            ATI

d—-        10/19/2006  11:48 AM            content

So, as you can see, PowerShell definitely deals with objects. When you?re using the Powershell.exe host, it might look like everything?s text, but that?s because the text is taking the shell engine?s objects and rendering them into text for you, using a set of rendering rules that help it provide the most important information about each object in a concise textual view.