Windows 7 : Scripting Windows with PowerShell - Scripting Objects

Scripting with PowerShell is really about scripting
objects, so the most fundamental skills you need to master PowerShell
scripting are those that enable you to work with and use objects.

In programming, an object is an element that exposes an interface to the programmer, who can then use that interface to work with the object in two ways:

Make changes to the object’s properties, which are the elements that describe or configure the object.

Make the object perform a task by activating one of the object’s methods, which are the elements that enable the object to perform actions.

In PowerShell, an object’s properties and methods are part of the collection known as the object’s members. Other items in an object’s member collection includes events (occurrences that trigger object actions) and property aliases (alternate names for certain properties).

Returning Object Members

When you need to work
with an object in PowerShell, you usually begin by listing all the
members associated with that object, which tells you which properties
you can read or change, and which methods you can invoke. To return an
object’s members, you use the Get-Member cmdlet:

object | get-member

Note

PowerShell’s pipe
operator (|) works just like it does in a Command Prompt session. That
is, it combines both input and output redirection, so that the output of
one cmdlet is captured and sent as input to another cmdlet.

Replace object
with the object you want to interrogate. For example, the following
command returns the members associated with the current location
(folder) in the PowerShell session:

Some member collections
are quite large and may displays dozens of properties, methods, and
other member types. If you’re only interested in a particular type of
member, you can restrict the output of Get-Member by adding the -MemberType switch:

object | get-member -membertype type1, type2, ...

Here, replace type1, type2, and so on with one or more of the following member type keywords: AliasProperty,
CodeProperty, Property, NoteProperty, ScriptProperty, Properties,
PropertySet, Method, CodeMethod, ScriptMethod, Methods,
ParameterizedProperty, MemberSet, Event, or All.

For example, if you only want to see the properties and methods associated with the Get-Process object (which returns a handle to a running process), enter the following command:

get-process | get-member -membertype property, method

Selecting Object Members

When you work with
an object, PowerShell usually defines a default subset of the object’s
members. For example, if you want to see a list of the running processes
on your system, you use the Get-Process cmdlet, which sends to the console output similar to the following:

These columns represent
(from left to right) the number of open handles, the amount of nonpaged
memory, the amount of paged memory, the size of the working set, the
amount of virtual memory, the amount of CPU time, the process ID, and
the process name. This is all useful information, but it might not be
what you want to see. For example, you might not need to see the number
of file handles each process is using, or you may be interested in not
only the current working set for each process, but also the peak working
set (the most memory the process has used in the current session).

In other words, there may be default properties that you don’t want to see, and other properties (such as PeakWorkingSet) that you do want to see. You can customize the members you work with by using the Select-Object cmdlet:

object | select-object member1[, member2, ...]

Here, object is the object you’re working with, and member1, member2, and so on are the members you want to use. Here’s an example:

get-process | select-object processname, workingset, peakworkingset

Tip

If you only want to see the first few results, add the -First
n switch, where n is the number of results you want to see. For example, the following command returns the first five results:

A Brief Aside About Formatting Output

If you run the command show
at the end of the previous section, the console displays the name,
working set, and peak working set for each running process. However, the
two memory values are displayed in bytes, rather than an easier-to-read
value such as kilobytes (as you get when you run Get-Process
by itself). To fix this, you need to define a statement that defines
how you want the output to look. In this case, the statement you want
takes the following general form:

@{Label="Label"; Expression={expression}}

Here, Label is the text you want to appear at the top of the output column, and expression
is an expression that defines how you want the values in that column to
appears. For example, to convert a memory value in bytes to kilobytes,
you need to divide it by 1,024:

[int]($_.workingset/1024)

We add [int] because we only want an integer result displayed. The symbols $_ are a PowerShell shorthand that refers to whatever object is currently being piped, so $_.workingset refers to the WorkingSet property of the current object. If we want the column name to be, say, WS (KB), the full statement looks like this:

@{Label="WS (KB)";Expression={[int]($_.workingset/1024)}}

We can do the same for the PeakWorkingSet property:

@{Label="Peak WS (KB)";Expression={[int]($_.peakworkingset/1024)}}

We then pipe everything through the Format-Table cmdlet using its -auto switch, which makes each column only wide enough to hold the widest item in the column:

Filtering Object Instances

By
default, PowerShell returns all the instances of an object. If you want
to work with only some subset of the object, you can use the Where-Object cmdlet to filter the instances and return just the ones you want. Here’s the general syntax:

object | where-object { expression }

Here, expression is a logical expression that defines the filter, and this expression usually takes the following general form:

property operator value

In this statement, property is the name of the object property you want to use as the filter, value is the text or numeric value you want to use as the comparison, and operator is one of the following PowerShell conditional operators:

-eq

Equals

-ne

Not equal

-gt

Greater than

-lt

Less than

-ge

Greater than or equal to

-le

Less than or equal to

-like

Match with wildcards

-notlike

No match with wildcards

-match

Match with regular expression

-notmatch

No match with regular expression

For example, suppose you want to work with processes via Get-Process, but you’re only interested in the PowerShell process. In that case, you’d filter the Get-Process output as follows:

You’ll probably find that the two wildcard operators are particularly useful. You use the standard wildcard characters: ? for a single characters, and *
for any number of characters. For example, to work with any process
that contains the string “powershell”, you’d use the following command:

Sorting Object Instances

When you work with the
instances of an object in PowerShell, those instances are sorted on the
object’s default property. For example, the instances returned by Get-Process are sorted on the ProcessName property. If you’d prefer to use the instances in some other order, you can use the Sort-Object cmdlet, which uses the following (partial) syntax:

object | sort-object -Property property [-Descending]

Here, property is the name of the property you want to use for the sort. For example, the following command sorts the output of the Get-Process cmdlet on the WorkingSet property values:

Assigning an Object to a Variable

In PowerShell, if
you want to work with an object’s properties or methods, you must first
use cmdlets to define your object, as described in the past few
sections, and then assign the result to a variable. Here’s the general
syntax:

$variable = object

For example, you saw earlier that the following command returns the PowerShell process:

get-process | where-object { $_.processname -eq "powershell" }

To access the properties and methods for this process, you need to assign the result to a variable, like so:

$ps = get-process | where-object { $_.processname -eq "powershell" }

In PowerShell, you always start a variable name with a dollar sign ($).

Working with Object Properties

Every programmable object has a defining set of characteristics. These characteristics are the object’s properties, and they control the appearance and position of the object. When you refer to a property, you use the following syntax:

Object.Property

Object

A variable containing the object instance

Property

The name of the property you want to work with

For example, suppose
you want to reference the current working set value for the PowerShell
process. In that case, you’d use cmdlets to filter Get-Process to just that instance, assign it to a variable, and then use that variable to access the WorkingSet property:

Returning the Value of a Property

Sometimes you need to know
the current setting of a property before changing the property or
performing some other action. You can find out the current value of a
property by using the following syntax:

$variable = Object.Property

Here, $variable
is a variable name. For example, if you have a process stored in a
variable, you can use that variable to return the value of the WorkingSet property. Here’s a sequence of commands that does this:

Setting the Value of a Property

When you pipe an object into Get-Members,
the resulting output includes a Definition column, and for Property
members the definition includes braces ({}) at the end, and within those
braces you see get if you can read the value of the property, and set if you can change the value of the property.

To set a property to a certain value, you use the following syntax:

Object.Property = value

Here, value
is an expression that specifies the value to which you want to set the
property. As such, it can be any of the scripting language’s recognized
data types, which usually include the following:

For example, each running process has a MaxWorkingSet property that determines the maximum amount of memory the process can use. Here’s a sequence of commands that sets the MaxWorkingSet property for a process to 20MB:

Working with Object Methods

An object’s properties describe what the object is, whereas its methods describe what the object does. For example, the WScript object has a Quit method that enables you to stop the execution of a script.

How you refer to a
method depends on whether the method requires any arguments. If it
doesn’t, the syntax is similar to that of properties:

Object.Method()

Object

The name of the object

Method

The name of the method you want to run

For example, each process has a Kill() method that shuts down the process. Here’s an example that runs this method:

Working with Object Collections

A collection is a set of similar objects. For example, when you run Get-Process
by itself, the return value is a collection of process objects.
Collections are objects, too, so they have their own properties and
methods, and you can use these properties and methods to manipulate one
or more objects in the collection.

To assign a collection to a variable, you use the following general syntax:

$variable = @(collection)

For example, the following command stores the collection of Get-Process instances in a variable:

$p = @(get-process)

The members of a collection are elements. You can refer to individual elements by using an index. For example, the following statement returns the name of the first process (collection indexes always begin at 0):

$p[0].name

Each collection has a Length property that tells you how many items are in the collection, which means that the expression Length-1 always refers to the last element in the collection:

$p[$_.length-1].workingset

If you don’t specify an element, PowerShell assumes that you want to work with the entire collection.

You often have to loop
through the individual elements in a collection and perform some action
on each element using one or more commands inside the loop. You use a foreach loop to do this:

foreach ($element in $collection) { [statements]}

$element

A variable used to hold the name of each element in the collection

$collection

A variable that stores the collection

statements

The statements to execute for each element in the collection

The multiline structure of a foreach
loop makes it better suited to a PowerShell script, but it’s possible
to run short loops at the console by putting everything on one line: