Section 3.2. Work with Structured Objects


3.2. Work with Structured Objects

Just as a DateTime object has properties for year, month, day, and so on, so too do the other types we've already seen. The Process class includes process ID, name, and other information, and the get-process cmdlet generates a sequence of objects, one for each process running on a system, with each of these values set accordingly. It's not immediately obvious from the output of get-process how much information is lurking within these objects. Next, we'll see that there's far more than just process name and ID.

Let's take a more detailed look at what these objects contain and howwith just the few cmdlets we've discussed so farthere's much more information waiting to be tapped.

Just How Much Information Is in There?

Judging by the output of the cmdlets we've discussed so far, there are plenty of useful properties to work withbut that's just the beginning. For common data types (including processes, files, and directories), the default formatter has a list of some typical properties. It's these properties that are shown in most of the output so far, but as we'll see in this section, the classes we've been using contain a wealth of information that isn't shown immediately. Fortunately, there are cmdlets that let us access just about any piece of the information we need.


3.2.1. How Do I Do That?

With all of the information stored inside these objects, we need a guidesomething that will help us get more familiar with these new data structures we're working with . The get-member cmdlet is here to make life easier. With no parameters, it lists every detail about the object. For the following examples, we'll be focusing on the properties (the "public" values and settings). Therefore, we'll tell get-member to just return those:

     MSH D:\MshScripts> get-process | get-member -MemberType Property         TypeName: System.Diagnostics.Process     Name                       MemberType Definition     ----                       ---------- ----------     BasePriority               Property   System.Int32 BasePriority {get;}     ExitCode                   Property   System.Int32 ExitCode {get;}     HasExited                  Property   System.Boolean HasExited {get;}     ExitTime                   Property   System.DateTime ExitTime {get;}     Handle                     Property   System.IntPtr Handle {get;}     HandleCount                Property   System.Int32 HandleCount {get;}     Id                         Property   System.Int32 Id {get;}     MachineName                Property   System.String MachineName {get;}     MainWindowHandle          Property   System.IntPtr MainWindowHandle {get;}     MainWindowTitle           Property   System.String MainWindowTitle {get;}     MainModule              Property   System.Diagnostics.ProcessModule MainM...     MaxWorkingSet             Property   System.IntPtr MaxWorkingSet {get;set;}     MinWorkingSet             Property   System.IntPtr MinWorkingSet {get;set;}     Modules                 Property   System.Diagnostics.ProcessModuleCollec...     NonpagedSystemMemorySize  Property System.Int32 NonpagedSystemMemorySize ...     NonpagedSystemMemorySize64 Property System.Int64 NonpagedSystemMemorySize6...     PagedMemorySize            Property   System.Int32 PagedMemorySize {get;}     PagedMemorySize64          Property   System.Int64 PagedMemorySize64 {get;}     PagedSystemMemorySize   Property   System.Int32 PagedSystemMemorySize {get;}     PagedSystemMemorySize64  Property  System.Int64 PagedSystemMemorySize64 {...     PeakPagedMemorySize      Property   System.Int32 PeakPagedMemorySize {get;}     PeakPagedMemorySize64   Property   System.Int64 PeakPagedMemorySize64 {get;}     PeakWorkingSet             Property   System.Int32 PeakWorkingSet {get;}     PeakWorkingSet64           Property   System.Int64 PeakWorkingSet64 {get;}     PeakVirtualMemorySize   Property   System.Int32 PeakVirtualMemorySize {get;}     PeakVirtualMemorySize64  Property  System.Int64 PeakVirtualMemorySize64 {...     PriorityBoostEnabled     Property  System.Boolean PriorityBoostEnabled {g...     PriorityClass          Property   System.Diagnostics.ProcessPriorityClas...     PrivateMemorySize          Property   System.Int32 PrivateMemorySize {get;}     PrivateMemorySize64      Property   System.Int64 PrivateMemorySize64 {get;}     PrivilegedProcessorTime  Property  System.TimeSpan PrivilegedProcessorTim...     ProcessName                Property   System.String ProcessName {get;}     ProcessorAffinity   Property   System.IntPtr ProcessorAffinity {get;s...     Responding                 Property   System.Boolean Responding {get;}     SessionId                  Property   System.Int32 SessionId {get;}     StartInfo           Property   System.Diagnostics.ProcessStartInfo St...     StartTime                  Property   System.DateTime StartTime {get;}     SynchronizingObject   Property   System.ComponentModel.ISynchronizeInvo...     Threads              Property   System.Diagnostics.ProcessThreadCollec...     TotalProcessorTime    Property   System.TimeSpan TotalProcessorTime {get;}     UserProcessorTime     Property   System.TimeSpan UserProcessorTime {get;}     VirtualMemorySize          Property   System.Int32 VirtualMemorySize {get;}     VirtualMemorySize64     Property   System.Int64 VirtualMemorySize64 {get;}     EnableRaisingEvents     Property   System.Boolean EnableRaisingEvents {ge...     StandardInput          Property   System.IO.StreamWriter StandardInput {...     StandardOutput         Property   System.IO.StreamReader StandardOutput ...     StandardError          Property   System.IO.StreamReader StandardError {...     WorkingSet                 Property   System.Int32 WorkingSet {get;}     WorkingSet64             Property   System.Int64 WorkingSet64 {get;}     Site                    Property   System.ComponentModel.ISite Site {get;...     Container               Property   System.ComponentModel.IContainer Conta...

Back to the output of get-process we saw earlier, it's clear that there is more information than the default view shows. For example, process names such as svchost and lsass can often be too cryptic to immediately understand their purpose. We can use a new cmdlet, select-object, to pick out a couple of interesting propertiesin this case, the process name and its longer description:

     MSH D:\MshScripts> get-process | select-object ProcessName,Description     ProcessName                             Description     -----------                             -----------     alg                                     Application Layer Gateway Service     CcmExec                                 CCM Executive     cmd                                     Windows Command Processor     cmd                                     Windows Command Processor     csrss     explorer                                Windows Explorer     Idle     lsass                                   LSA Shell (Export Version)     msh                                     msh     notepad                                 Notepad     notepad                                 Notepad     ntvdm                                   NTVDM.EXE     regedit                                 Registry Editor     services                                Services and Controller app     smss                                    Windows NT Session Manager     ...

As we've already seen, get-process can take a parameter for matching a process name; in this case, we'll specify msh. By enclosing the cmdlet and parameters in parentheses, we're now able to access properties on the object that it returns:

     MSH D:\MshScripts> (get-process msh).Threads     BasePriority            : 8     CurrentPriority         : 8     Id                      : 1716     IdealProcessor          :     PriorityBoostEnabled    : True     PriorityLevel           : Normal     PrivilegedProcessorTime : 00:00:01.0414976     StartAddress            : 2011608519     StartTime               : 5/20/2005 4:26:17 PM     ThreadState             : Ready     TotalProcessorTime      : 00:00:04.7167824     UserProcessorTime       : 00:00:03.6752848     WaitReason              :     ProcessorAffinity       :     Site                    :     Container               :     BasePriority            : 8      CurrentPriority         : 8     Id                      : 1136     IdealProcessor          :     PriorityBoostEnabled    : True     PriorityLevel           : Normal     PrivilegedProcessorTime : 00:00:00     StartAddress            : 2011608507     StartTime               : 5/20/2005 4:26:17 PM     ThreadState             : Wait     TotalProcessorTime      : 00:00:00     UserProcessorTime       : 00:00:00     WaitReason              : UserRequest     ProcessorAffinity       :     Site                    :     Container               :     BasePriority            : 10     CurrentPriority         : 12     Id                      : 916     IdealProcessor          :     PriorityBoostEnabled    : True     PriorityLevel           : Highest     PrivilegedProcessorTime : 00:00:00.8412096     StartAddress            : 2011608507     StartTime               : 5/20/2005 4:26:17 PM     ThreadState             : Wait     TotalProcessorTime      : 00:00:03.9657024     UserProcessorTime       : 00:00:03.1244928     WaitReason              : UserRequest     ProcessorAffinity       :     Site                    :     Container               :     ...

Now let's take a look at another set of data associated with each process: its Modules property, which is a collection of all of the assemblies and DLLs used by the process. Because that's probably going to be a long list, we'll use where-object to select just those that are greater than 5 MB in size:

     MSH D:\MshScripts> (get-process msh).Modules | where-object     {$_.ModuleMemorySize -gt 5M}           Size ModuleName                                         FileName           ---- ----------                                         --------         5,076k mscorwks.dll                                    C:\WINDOWS\Mic...        10,392k mscorlib.ni.dll                                 C:\WINDOWS\ass...         8,256k shell32.dll                                     C:\WINDOWS\sys...         7,696k System.ni.dll                                   C:\WINDOWS\ass...        10,512k System.Xml.ni.dll                               C:\WINDOWS\ass...         6,776k System.Data.ni.dll                              C:\WINDOWS\ass...

3.2.2. What Just Happened?

get-member is useful for finding out property names and values if you're not familiar with the class you're dealing with. Because Process objects have many properties and methods, we used the MemberType parameter to select just a subset. Feel free to explore the output when no member type is specified. You'll see how much information is available from a seemingly simple command.

From what we saw in the previous section, it seems as though get-member should be run on every running process (since there will be a corresponding object for each in the pipeline). If that's the case, why did we see the properties only once? As get-member is commonly used on a stream of identical classes, its default behavior is to list only the members of a type it hasn't seen yet. If, for some reason, you need get-member to list for every type, this behavior can be overridden with the -ForEachObject option.

select-object is a useful tool for simplifying objects as they pass through the pipeline. Given a number of properties of interest, it will take these from each object it sees and create a simple new object with just these fields. This can bring about performance gains (since the new objects are significantly smaller) and simplify downstream processing.

Here we also see a new conceptthe idea of a collection. When dealing with the THReads property, instead of seeing just a single value (as we did with ProcessName, for example), we get back a sequence of objects, one for each of the threads in the process. These objects are put into the pipeline, in order, which means that we can now use the familiar, group-object, sort-object, and where-object cmdlets on this data.

3.2.3. What About...

...Supplying other properties to select-object? In the previous example, ProcessName and Description might not be the two most useful fields to select. By all means, feel free to pick out other properties to meet your own needs; any of the properties revealed by get-member are fair game:

     MSH D:\MshScripts> get-process | select-object Id,Name,Threads

...Using MSH to determine which processes are using a certain module? By combining a handful of cmdlets together, we can filter the Modules list to select just those processes that match specific criteria. Let's say we're interested in finding all processes using the Crypto API that is located in the file crypt32.dll. We use the -Expand option on select-object to break each process's Modules collection into separate ProcessModule objects. Instead of the whole Modules collection going into the pipeline in one big chunk, each of the ProcessModule objects will go through in turn (accompanied by the Id and ProcessName properties of the parent Process):

     MSH D:\MshScripts> get-process | select-object Id,ProcessName -Expand     Modules | where-object {$_.ModuleName -eq "CRYPT32.dll"} | select-object     Id,ProcessName

Collections have properties that differ from those of the objects they contain. Looking back at the contents of the Threads property output, it's clear that there are a number of threads; we saw the details of each in turn. The option -InputObject on get-member can be used to inspect the THReads collection rather than the properties of the ProcessThread objects it contains:

     MSH D:\MshScripts> get-member -InputObject (get-process msh).Threads         TypeName: System.Diagnostics.ProcessThreadCollection     Name          MemberType Definition     ----          ---------- ----------     Count         Property   System.Int32 Count {get;}     get_Item      Method     ProcessThread get_Item(Int32 index)     Add           Method     Int32 Add(ProcessThread thread)     Insert        Method     Void Insert(Int32 index, ProcessThread thread)     IndexOf       Method     Int32 IndexOf(ProcessThread thread)     Contains      Method     Boolean Contains(ProcessThread thread)     Remove        Method     Void Remove(ProcessThread thread)     CopyTo        Method     Void CopyTo(ProcessThread[] array, Int32 index)     get_Count     Method     Int32 get_Count(  )     GetEnumerator Method     IEnumerator GetEnumerator(  )     GetType       Method     Type GetType(  )     ToString      Method     String ToString(  )     Equals        Method     Boolean Equals(Object obj)     GetHashCode   Method     Int32 GetHashCode(  )

Note that we couldn't just do (get-process msh).Threads | get-member; that would have caused automatic expansion of the Threads collection, resulting in get-member showing the properties of the individual objects contained within. As it stands, we see that the Threads collection has a Count property that seems to be what we're looking for. Using the same dot notation as earlier, we can easily get a tally of the threads in use. Note that you might get a different number of threads when trying this on your own machinethat just shows that the expression is returning the number of threads running inside your MSH process:

     MSH D:\MshScripts> (get-process msh).Threads.Count     7

3.2.4. Where Can I Learn More?

The built-in help for the two new commands we've covered in this section has further usage information:

     MSH D:\MshScripts> get-help get-member     MSH D:\MshScripts> get-help select-object




Monad Jumpstart
Monad Jumpstart
ISBN: N/A
EAN: N/A
Year: 2005
Pages: 117

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net