What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

The text output of commands in the PowerShell interpreter window is just a way to display information in a human-readable form. Actually Wednesday oriented to work with objects: cmdlets and functions receive them as input and return at the exit, and the variable types available interactively and in scripts are based on .NET classes. In the fourth article of the series, we will study working with objects in more detail.

Table of Contents:

Objects in PowerShell
Viewing the Structure of Objects
Object filtering
Sorting objects
Selection of objects and their parts
ForEach-Object, Group-Object and Measure-Object
Creating .NET and COM Objects (New-Object)
Calling static methods
Type PSCustomObject
Creating Your Own Classes

Objects in PowerShell

Recall that an object is a collection of data fields (properties, events, etc.) and ways of processing them (methods). Its structure is given by a type, which is typically based on the classes used in the .NET Core unified platform. It is also possible to work with COM, CIM (WMI) and ADSI objects. Properties and methods are needed to perform various actions on data, in addition, in PowerShell, objects can be passed as arguments to functions and cmdlets, assign their values ​​to variables, and there is also command composition mechanism (conveyor or pipeline). Each command in the pipeline passes its output to the next in turn, object by object. For processing, you can use compiled cmdlets or create your own advanced featuresto perform various manipulations with objects in the pipeline: filtering, sorting, grouping, and even changing their structure. Transferring data in this form has a significant advantage: the receiving team does not need to parse the stream of bytes (text), all the necessary information is easily retrieved by accessing the appropriate properties and methods.

Viewing the Structure of Objects

For example, let's run the Get-Process cmdlet, which allows you to get information about the processes running in the system:

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

It will display some formatted text data that does not give an idea about the properties of the returned objects and their methods. To fine-tune the output, you need to learn how to examine the structure of objects, and the Get-Member cmdlet will help us with this:

Get-Process | Get-Member

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Here we already see the type and structure, and with the help of additional parameters we can, for example, display only the properties of the object that got to the input:

Get-Process | Get-Member -MemberType Property

You will need this knowledge to solve administrative tasks interactively or to write your own scripts: for example, to get information about hung processes by the Responding property.

Object filtering

PowerShell allows you to pipe objects that meet a certain condition:

Where-Object { блок сценария }

The result of executing a script block within operator brackets must be a boolean value. If it is true ($true), the object that got into the input of the Where-Object cmdlet will be passed down the pipeline, otherwise (value $false) it will be deleted. For example, let's display a list of stopped Windows Server services, i.e. those with the Status property set to "Stopped":

Get-Service | Where-Object {$_.Status -eq "Stopped"}

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Here again we see a textual representation, but if you want to understand the type and internal structure of the objects passing through the pipeline, it is not difficult:

Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Sorting objects

When objects are pipelined, it is often necessary to sort them. The Sort-Object cmdlet is passed the names of the properties (sort keys) and returns the objects sorted by their values. The output of running processes can be easily sorted by CPU time spent (cpu property):

Get-Process | Sort-Object –Property cpu

The -Property parameter can be omitted when calling the Sort-Object cmdlet and is used by default. For reverse sorting, the -Descending parameter is used:

Get-Process | Sort-Object cpu -Descending

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Selection of objects and their parts

The Select-Object cmdlet allows you to select a specific number of objects at the beginning or end of a pipeline using the -First or -Last options. With it, you can select single objects or specific properties, as well as create new objects based on them. Let's analyze the work of the cmdlet using simple examples.

The following command displays information about the 10 processes consuming the maximum amount of RAM (WS property):

Get-Process | Sort-Object WS -Descending | Select-Object -First 10

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

You can select only certain properties of objects passing through the pipeline and create new ones based on them:

Get-Process | Select-Object ProcessName, Id -First 1

As a result of the pipeline, we will get a new object, the structure of which will differ from the structure returned by the Get-Process cmdlet. Verify this with Get-Member:

Get-Process | Select-Object ProcessName, Id -First 1 | Get-Member

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Note that Select-Object returns a single object (-First 1) that has only the two fields we specified: their values ​​were copied from the first object passed into the pipeline by the Get-Process cmdlet. One of the ways to create objects in PowerShell scripts is based on the use of Select-Object:

$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType()

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

With Select-Object, you can add computed properties to objects that you want to represent as hash tables. In this case, the value of its first key corresponds to the property name, and the value of the second key corresponds to the property value for the current pipeline element:

Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}}

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Let's look at the structure of the objects passing through the pipeline:

Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} | Get-Member

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

ForEach-Object, Group-Object and Measure-Object

There are other cmdlets for working with objects. For example, let's talk about the three most useful:

ForEach-Object allows you to execute PowerShell code for each object in the pipeline:

ForEach-Object { блок сценария }

Group-Object groups objects by property value:

Group-Object PropertyName

If you run it with the -NoElement parameter, you can find out the number of elements in groups.

Measure-Object aggregates various summary parameters by the values ​​of the fields of objects in the pipeline (calculates the sum, and also finds the minimum, maximum, or average value):

Measure-Object -Property PropertyName -Minimum -Maximum -Average -Sum

Typically, the discussed cmdlets are used in interactive mode, and scripts are more often created Features with Begin, Process and End blocks.

Creating .NET and COM Objects (New-Object)

There are many software components with .NET Core and COM interfaces that are useful to system administrators. With the System.Diagnostics.EventLog class, you can manage system logs directly from Windows PowerShell. Let's look at an example of creating an instance of this class using the New-Object cmdlet with the -TypeName parameter:

New-Object -TypeName System.Diagnostics.EventLog

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Because we didn't specify a specific event log, the resulting class instance contains no data. To change this, you need to call a special constructor method during its creation using the -ArgumentList parameter. If we want to access the application log, the string "Application" should be passed to the constructor as an argument:

$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Please note that we saved the output of the command in the $AppLog variable. While pipelines are commonly used interactively, scripting often requires maintaining a reference to an object. Also, the core .NET Core classes are contained in the System: namespace by default. PowerShell looks for the specified types in it, so writing Diagnostics.EventLog instead of System.Diagnostics.EventLog is fine.

To work with the log, you can refer to the corresponding methods:

$AppLog | Get-Member -MemberType Method

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Let's say it is cleared by the Clear() method if there are access rights:

$AppLog.Clear()

The New-Object cmdlet is also used to work with COM components. There are quite a few of them, from the libraries that come with Windows Script Server to ActiveX applications such as Internet Explorer. To create a COM object, you need to specify the -ComObject parameter with the programmatic ProgId of the desired class:

New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObject

To create your own objects with an arbitrary structure, using New-Object looks too archaic and cumbersome, this cmdlet is used to work with program components external to PowerShell. Future articles will address this issue in more detail. In addition to .NET and COM objects, we will also explore CIM (WMI) and ADSI objects.

Calling static methods

Some .NET Core classes cannot be instantiated, including System.Environment and System.Math. They are static and contain only static properties and methods. In essence, these are reference libraries that are used without creating objects. You can refer to a static class as a literal by enclosing the type name in square brackets. At the same time, if we look at the structure of the object using Get-Member, we will see the System.RuntimeType type instead of System.Environment:

[System.Environment] | Get-Member

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

To view only static members, you need to call Get-Member with the -Static parameter (pay attention to the type of the object):

[System.Environment] | Get-Member -Static

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

To access static properties and methods, two consecutive colons are used instead of a dot after the literal:

[System.Environment]::OSVersion

Or

$test=[System.Math]::Sqrt(25) 
$test
$test.GetType()

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Type PSCustomObject

Among the numerous data types available in PowerShell, it is worth mentioning PSCustomObject, which is designed to store objects with an arbitrary structure. Creating such an object using the New-Object cmdlet is considered a classic, but cumbersome and outdated way:

$object = New-Object  –TypeName PSCustomObject -Property @{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'}

Let's look at the structure of the object:

$object | Get-Member

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Starting with PowerShell 3.0, another syntax is available:

$object = [PSCustomObject]@{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'
}

You can access the data in one of the equivalent ways:

$object.Name

$object.'Name'

$value = 'Name'
$object.$value

Here is an example of converting an existing hashtable into an object:

$hash = @{'Name'='Ivan Danko'; 'City'='Moscow'; 'Country'='Russia'}
$hash.GetType()
$object = [pscustomobject]$hash
$object.GetType()

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

One of the disadvantages of objects of this type is that the order of their properties can change. To avoid this, you need to use the [ordered] attribute:

$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'
}

There are other options for creating an object: above, we looked at using the cmdlet Select-Object. It remains to deal with adding and removing elements. Doing this for the object from the previous example is quite simple:

$object | Add-Member –MemberType NoteProperty –Name Age  –Value 33
$object | Get-Member

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

The Add-Member cmdlet allows you to add not only properties, but also methods to a previously created $object by using the "-MemberType ScriptMethod" construct:

$ScriptBlock = {
    # код 
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member

Note that we used the $ScriptBlock variable of the ScriptBlock type to store the code for the new method.

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

To remove properties, use the corresponding method:

$object.psobject.properties.remove('Name')

Creating Your Own Classes

PowerShell 5.0 introduced the ability to define classes using the syntax characteristic of object-oriented programming languages. The Class keyword is used for this, after which you should specify the class name and describe its body in operator brackets:

class MyClass
{
    # тело класса
}

This is a true .NET Core type, and its body describes its properties, methods, and other elements. Consider an example of a simple class definition:

class MyClass 
{
     [string]$Name
     [string]$City
     [string]$Country
}

To create an object (an instance of a class), use the cmdlet New-Object, or a literal of type [MyClass] and pseudostatic method new (default constructor):

$object = New-Object -TypeName MyClass

or

$object = [MyClass]::new()

Let's analyze the structure of the object:

$object | Get-Member

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Don't forget about scope: you can't refer to a type name as a string or use a type literal outside of the script or module in which the class is defined. At the same time, functions can return class instances (objects) that will be available outside the module or script.

After creating the object, fill in its properties:

$object.Name = 'Ivan Danko'
$object.City = 'Moscow'
$object.Country = 'Russia'
$object

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Note that in the class description, not only the types of properties are specified, but also their default values:

class Example
{
     [string]$Name = 'John Doe'
}

The description of a class method resembles a description of a function, but without the function word. As in functions, parameters are passed to methods if necessary:

class MyClass 
{
     [string]$Name
     [string]$City
     [string]$Country
     
     #описание метода
     Smile([bool]$param1)
     {
         If($param1) {
            Write-Host ':)'
         }
     }
}

Now the representative of our class knows how to smile:

$object = [MyClass]::new()
$object.Smile($true)

Methods can be overloaded, in addition, the class has static properties and methods, as well as constructors whose names match the name of the class itself. A class defined in a script or a PowerShell module can serve as a base class for another - this is how inheritance is implemented. At the same time, existing .NET classes can be used as base ones:

class MyClass2 : MyClass
{
      #тело нового класса, базовым для которого является MyClass
}
[MyClass2]::new().Smile($true)

Our description of working with objects in PowerShell is hardly exhaustive. In the following publications, we will try to deepen it with practical examples: the fifth article of the series will be devoted to integration of PowerShell with third-party software components. Past parts can be found at the links below.

Part 1: Key features of Windows PowerShell
Part 2: Introduction to the Windows PowerShell Programming Language
Part 3: passing parameters to scripts and functions, creating cmdlets

What is Windows PowerShell and what is it eaten with? Part 4: Working with objects, own classes

Source: habr.com

Add a comment