Weekend Scripter: Use PowerShell to Work with Embedded Objects


Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to work with embedded objects.

Microsoft Scripting Guy, Ed Wilson, is here. This morning I have my Zune 1.0 cranked up, and I am listening to some tunes. I have a nice cup of English Breakfast tea, and a warm croissant beside me. I also was able to score some homemade orange marmalade.

Anyway, a few years ago, the Scripting Wife and I were in Maui, Hawaii, and we took an early morning drive up a winding road. We entered clouds, and it seemed like it was raining. I thought about turning back because of the rain, but there was no good place to turn. Then we emerged from the clouds, and the view was way cool. Here is a picture:

Photo of landscape

It was like another world that was hidden by the clouds below. In some respect, that is the way embedded objects in Windows PowerShell objects appear.

Here is a basic example of embedded objects. When I use the Get-Process cmdlet to look at a specific process, such as Notepad, Windows PowerShell returns basic information. Often the information like that shown here is enough:

PS C:\> Get-Process notepad

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName                           

-------  ------    -----      ----- -----   ------     -- -----------                           

     85       8     1636       9800   113     0.05   6220 notepad     

If I want to see more information, I pipe the resulting object to the Format-List cmdlet and select all of the properties:

PS C:\> Get-Process notepad | fl *

__NounName                 : Process

Name                       : notepad

Handles                    : 85

VM                         : 118321152

WS                         : 10035200

PM                         : 1675264

NPM                        : 8688

Path                       : C:\Windows\System32\notepad.exe

Company                    : Microsoft Corporation

CPU                        : 0.046875

FileVersion                : 6.3.9600.16384 (winblue_rtm.130821-1623)

ProductVersion             : 6.3.9600.16384

Description                : Notepad

Product                    : Microsoft® Windows® Operating System

Id                         : 6220

PriorityClass              : Normal

HandleCount                : 85

WorkingSet                 : 10035200

PagedMemorySize            : 1675264

PrivateMemorySize          : 1675264

VirtualMemorySize          : 118321152

TotalProcessorTime         : 00:00:00.0468750

BasePriority               : 8

ExitCode                   :

HasExited                  : False

ExitTime                   :

Handle                     : 3132

MachineName                : .

MainWindowHandle           : 2361006

MainWindowTitle            : Untitled - Notepad

MainModule                 : System.Diagnostics.ProcessModule (notepad.exe)

MaxWorkingSet              : 1413120

MinWorkingSet              : 204800

Modules                    : {System.Diagnostics.ProcessModule (notepad.exe),

                             System.Diagnostics.ProcessModule (ntdll.dll),

                             System.Diagnostics.ProcessModule (KERNEL32.DLL),

                             System.Diagnostics.ProcessModule (KERNELBASE.dll)...}

NonpagedSystemMemorySize   : 8688

NonpagedSystemMemorySize64 : 8688

PagedMemorySize64          : 1675264

PagedSystemMemorySize      : 231168

PagedSystemMemorySize64    : 231168

PeakPagedMemorySize        : 1675264

PeakPagedMemorySize64      : 1675264

PeakWorkingSet             : 10072064

PeakWorkingSet64           : 10072064

PeakVirtualMemorySize      : 118374400

PeakVirtualMemorySize64    : 2199141629952

PriorityBoostEnabled       : True

PrivateMemorySize64        : 1675264

PrivilegedProcessorTime    : 00:00:00.0468750

ProcessName                : notepad

ProcessorAffinity          : 255

Responding                 : True

SessionId                  : 1

StartInfo                  : System.Diagnostics.ProcessStartInfo

StartTime                  : 4/4/2015 1:39:29 PM

SynchronizingObject        :

Threads                    : {4012}

UserProcessorTime          : 00:00:00

VirtualMemorySize64        : 2199141576704

EnableRaisingEvents        : False

StandardInput              :

StandardOutput             :

StandardError              :

WorkingSet64               : 10035200

Site                       :

Container                  :

As you can see, the Modules, MainModule, and StartInfo objects contain other objects. As an example, here is the StartInfo object:

PS C:\> Get-Process notepad | select startinfo

StartInfo                                                                                       

---------                                                                                       

System.Diagnostics.ProcessStartInfo       

I can look up the object on MSDN, but I am not sure if it is worth the trouble. I can also use what I call “group and dot.”  All I need to do is put parentheses around the object, and select the StartInfo property. When I do this, I can see everything that is contained in the object. This is shown here:

PS C:\> (Get-Process notepad).startinfo

Verb                    :

Arguments               :

CreateNoWindow          : False

EnvironmentVariables    : {ProgramW6432, Path, PROCESSOR_IDENTIFIER, TEMP...}

RedirectStandardInput   : False

RedirectStandardOutput  : False

RedirectStandardError   : False

StandardErrorEncoding   :

StandardOutputEncoding  :

UseShellExecute         : True

Verbs                   : {}

UserName                :

Password                :

Domain                  :

LoadUserProfile         : False

FileName                :

WorkingDirectory        :

ErrorDialog             : False

ErrorDialogParentHandle : 0

WindowStyle             : Normal

One of the cool things I can do, is continue down the road. I can use a double dot (if you will), and select the WindowStyle property from the ProcessStartInfo object. Because I have already seen that (Get-Process notepad).StartInfo returns a ProcessStartInfo object, I know that I can return a single property from this object. This technique is shown here:

PS C:\> (Get-Process notepad).startinfo.WindowStyle

Normal

Windows PowerShell also has a built-in method of handling this situation. I can use the –ExpandProperty parameter from the Select-Object cmdlet. This is faster (for me) than using the “group and dot” technique because I do not have to back up on the command line. Here is the command:

PS C:\> Get-Process notepad | select -ExpandProperty startinfo

Verb                    :

Arguments               :

CreateNoWindow          : False

EnvironmentVariables    : {ProgramW6432, Path, PROCESSOR_IDENTIFIER, TEMP...}

RedirectStandardInput   : False

RedirectStandardOutput  : False

RedirectStandardError   : False

StandardErrorEncoding   :

StandardOutputEncoding  :

UseShellExecute         : True

Verbs                   : {}

UserName                :

Password                :

Domain                  :

LoadUserProfile         : False

FileName                :

WorkingDirectory        :

ErrorDialog             : False

ErrorDialogParentHandle : 0

WindowStyle             : Normal

This is good information, and it shows me what property contains, but it does not help me match it with the process name. What if I also want to see the process name? I specify the Property name in addition to the property I want to expand:

PS C:\> Get-Process notepad | Select -Property name -ExpandProperty startinfo

Name                    : notepad

Verb                    :

Arguments               :

CreateNoWindow          : False

EnvironmentVariables    : {ProgramW6432, Path, PROCESSOR_IDENTIFIER, TEMP...}

RedirectStandardInput   : False

RedirectStandardOutput  : False

RedirectStandardError   : False

StandardErrorEncoding   :

StandardOutputEncoding  :

UseShellExecute         : True

Verbs                   : {}

UserName                :

Password                :

Domain                  :

LoadUserProfile         : False

FileName                :

WorkingDirectory        :

ErrorDialog             : False

ErrorDialogParentHandle : 0

WindowStyle             : Normal

What if I am only interested in the WindowStyle property from the StartInfo object? I can create a custom property by using a hash table with the Select-Object cmdlet. This technique involves specifying a label and an expression. The label is a string, and it can be abbreviated as L. The expression is a script block, and can be abbreviated as E. Here is an example:

Get-Process notepad | select -Property name, @{L="Style";E={$_.startinfo.WindowStyle}}

When I run this, it returns the following custom object:

Image of command output

This will work for all processes, for a single process, and for other embedded objects.

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

Comments (1)

Skip to main content