A PowerShell-interpreter's text output is simply a way to display information in a human-readable format. In reality, the environment is designed to work with objects: cmdlets and functions receive them as input and , while the types of variables available in interactive mode and scripts are based on .NET classes. In the fourth article of the series, we will examine working with objects in more detail.
Tartalomjegyzék:
Objects in PowerShell
Recall that an object is a collection of data fields (properties, events, etc.) and methods to process them. Its structure is defined by a type, which is generally based on the classes used in the unified .NET Core platform. There is also the possibility to work with COM, CIM (WMI), and ADSI objects. Properties and methods are necessary for performing various actions on data, and in PowerShell, objects can be passed as arguments to functions and cmdlets, assign their values to variables, and there is a (pipeline). Each command in the pipeline passes its output to the next one sequentially—object by object. You can use compiled cmdlets for processing or create your own , to perform various manipulations with objects in the pipeline: filtering, sorting, grouping, and even changing their structure. Transmitting data in this way has a significant advantage: the receiving command does not need to parse the byte stream (text), all the necessary information is easily extracted by accessing the corresponding properties and methods.
Viewing the structure of objects
For example, let’s run the Get-Process cmdlet, which allows obtaining information about the processes running in the system:

It will display formatted text data on the screen, which does not give a clear representation of the properties of the returned objects and their methods. To refine the output, it is necessary to learn how to explore the structure of objects, and for that, we have the Get-Member cmdlet:
Get-Process | Get-Member 
Itt már látjuk a típust és a struktúrát, és a kiegészítő paraméterek segítségével például csak a bemeneti objektum tulajdonságait jeleníthetjük meg:
Get-Process | Get-Member -MemberType PropertyEzek a tudások szükségesek az interaktív üzemmódban való adminisztrációs feladatok megoldásához, vagy saját szkriptek írásához: mondjuk, hogy információt nyerjünk a leállt folyamatokról a Responding tulajdonság alapján.
Filtering objects
A PowerShell lehetővé teszi olyan objektumok átengedését a csövön, amelyek megfelelnek egy adott feltételnek:
Where-Object { szkript blokk }A szkript blokk végrehajtásának eredményeként logikai értéket kell kapnunk. Ha ez igaz ($true), a Where-Object parancsnak átadott bemeneti objektum tovább lesz küldve a csövön, különben (ha az érték $false) eltávolításra kerül. Példaként megjelenítjük a Windows Server leállt szolgáltatásainak listáját, azaz azokat, amelyeknek a Status tulajdonsága "Stopped":
Get-Service | Where-Object {$_.Status -eq "Stopped"} 
Itt újra egy szöveges reprezentációt látunk, de ha szeretnénk érteni a csövön keresztül haladó objektumok típusát és belső felépítését, az nem nehéz:
Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member 
Sorting objects
Objektumok csöves feldolgozása során gyakran szükség van azok rendezésére. A Sort-Object parancsnak a rendezési kulcsok (tulajdonságnevek) átadására van szüksége, és ő a rendezett objektumokat adja vissza értékeik alapján. A futó folyamatok kimenete könnyen rendezhető a CPU használt idő szerint:
Get-Process | Sort-Object –Property cpuA Sort-Object parancs hívásakor nem szükséges megadni a -Property paramétert — az alapértelmezés szerint alkalmazva van. Fordított rendezéshez a -Descending paraméter használható:
Get-Process | Sort-Object cpu -Descending 
Extracting objects and their parts
A Select-Object parancs lehetővé teszi, hogy kiválasszunk egy meghatározott számú objektumot a cső elején vagy végén, a -First vagy -Last paraméterek segítségével. Ezen keresztül kiválaszthatunk egyedi objektumokat vagy bizonyos tulajdonságokat, és új objektumokat hozhatunk létre az alapjukon. Vizsgáljuk meg a parancs működését egyszerű példákon.
A következő parancs megjeleníti a legnagyobb memóriahasználatú (WS tulajdonságú) 10 folyamat információját:
Get-Process | Sort-Object WS -Descending | Select-Object -First 10 
Csak bizonyos tulajdonságokat is kiemelhetünk a csövön átmenő objektumok közül, és új objektumokat hozhatunk létre belőlük:
Get-Process | Select-Object ProcessName, Id -First 1A csőmunka eredményeként új objektumot kapunk, amelynek struktúrája eltér a Get-Process parancsfájl által visszaadott struktúrától. Ezt a Get-Member segítségével fogjuk ellenőrizni:
Get-Process | Select-Object ProcessName, Id -First 1 | Get-Member 
Figyeljük meg, hogy a Select-Object egyetlen objektumot ad vissza (-First 1), amelynek csupán két, általunk megadott mezője van: ezek értékei az első, a csővezetékben átadott Get-Process parancsfájl által visszaadott objektumból lettek másolva. A Select-Object használatán alapul a PowerShell szkriptek egyik módszere az objektumok létrehozására:
$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType() 
A Select-Object segítségével számított tulajdonságokat lehet hozzáadni az objektumokhoz, amelyeknek meg kell jelenniük . Az első kulcsának értéke a tulajdonság neve, a második kulcsának értéke pedig a tulajdonság értéke az aktuális csővezeték elemhez:
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} 
Nézzük meg a csővezeték során átmenő objektumok struktúráját:
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} | Get-Member 
ForEach-Object, Group-Object, and Measure-Object
Más parancsfájlok is léteznek az objektumokkal való munkához. Példaként három hasznos parancsfájlt ismertetünk:
ForEach-Object az lehetővé teszi, hogy kódot futtassunk PowerShell nyelven minden objektumra a csővezetékben:
ForEach-Object { szkript blokk }Group-Object csoportosítja az objektumokat a tulajdonság értéke szerint:
Group-Object PropertyNameHa a -NoElement paraméterrel futtatjuk, megtudhatjuk a csoportokban lévő elemek számát.
Measure-Object aggregálja a különböző összesítő paramétereket az objektumok mezőértékein (összeget számít, és meghatározza a minimum, maximum vagy átlag értéke):
Measure-Object -Property PropertyName -Minimum -Maximum -Average -SumÁltalában a fent említett parancsfájlokat interaktív módban használják, míg a szkriptek gyakran blokkokkal kerülnek létrehozásra: Begin, Process és End.
Creating .NET and COM objects (New-Object)
Számos .NET Core és COM interfésszel rendelkező programkomponens létezik, amelyek hasznosak a rendszergazdák számára. A System.Diagnostics.EventLog osztály segítségével közvetlenül a Windows PowerShellből kezelhetők a rendszer naplói. Nézzük meg a példát, hogyan hozzunk létre egy példányt ebből az osztályból a New-Object parancsfájl segítségével, a -TypeName paraméterrel:
New-Object -TypeName System.Diagnostics.EventLog 
Mivel nem adtunk meg meghatározott eseménynaplót, a létrehozott osztálypéldány nem tartalmaz adatokat. Ennek megváltoztatásához a létrehozás során egy speciális konstruktor metódust kell hívnunk az -ArgumentList paraméter segítségével. Ha hozzáférést szeretnénk kapni az alkalmazásnaplóhoz, a konstruktorban az 'Application' sztringet kell argumentumként átadni:
$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog 
Kérjük, vegye figyelembe: a parancs kimenetét $AppLog változóba mentettük. Bár interaktív módban általában csövek használatosak, a szkriptek írása gyakran megkívánja, hogy a hivatkozást objektumra megőrizzük. Ezenkívül a .NET Core alapvető osztályai a System névtérben találhatóak: a PowerShell alapértelmezetten itt keresi a megadott típusokat, így a Diagnostics.EventLog írása a System.Diagnostics.EventLog helyett teljesen helyes.
A napló kezelésére a megfelelő metódusokhoz lehet hozzáférni:
$AppLog | Get-Member -MemberType Method 
Tegyük fel, hogy a Clear() metódus segítségével töröljük, amennyiben van hozzáférési jogunk:
$AppLog.Clear()A New-Object parancsmag szintén használható COM-összetevők kezelésére. Ezekből meglehetősen sok van — a Windows szerverhez szállított szkriptek könyvtáraitól kezdve az ActiveX alkalmazásokig, például az Internet Explorerig. COM-objektum létrehozásához a -ComObject paramétert kell megadni a kívánt osztály ProgId programazonosítójával:
New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObjectSaját, tetszőleges struktúrájú objektumok létrehozásához a New-Object használata túlságosan elavultnak és terjedelmesnek tűnik, ez a parancsmag külső PowerShell-en kívüli programkomponensek kezelésére szolgál. A következő cikkekben ezt a kérdést részletesebben megvizsgáljuk. A .NET és COM objektumok mellett a CIM (WMI) és ADSI objektumokat is tanulmányozni fogunk.
Calling static methods
Bizonyos .NET Core osztályok példányait nem lehet létrehozni: ezek közé tartozik a System.Environment és a System.Math. Ezek és csak statikus tulajdonságokat és metódusokat tartalmaznak. Valójában ez egy hivatkozási könyvtár, amelyet objektumok létrehozása nélkül használnak. Egy statikus osztályra a típusnevet négyzetes zárójelek közé zárva lehet hivatkozni. Ezen kívül, ha a Get-Member segítségével megnézzük az objektum struktúráját, a System.RuntimeType típust fogjuk látni a System.Environment helyett:
[System.Environment] | Get-Member 
A statikus elemek megtekintéséhez a Get-Member parancsot a -Static paraméterrel kell meghívni (figyeljünk az objektum típusára):
[System.Environment] | Get-Member -Static 
A statikus tulajdonságokhoz és metódusokhoz a literál után két egymást követő kettőspontot kell használni a pont helyett:
[System.Environment]::OSVersionVagy
$test=[System.Math]::Sqrt(25)
$test
$test.GetType() 
PSCustomObject Type
A PowerShell-ben elérhető számos adat típusa közül kiemelendő a PSCustomObject, amelyet önálló szerkezetű objektumok tárolására terveztek. Ennek a New-Object parancsmaggal való létrehozása klasszikus, de nehézkes és elavult módszer:
$object = New-Object –TypeName PSCustomObject -Property @{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'}
Nézzük meg az objektum szerkezetét:
$object | Get-Member 
A PowerShell 3.0-tól kezdve egy másik szintaxis is elérhető:
$object = [PSCustomObject]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Az adatokhoz egyenértékű módokon lehet hozzáférni:
$object.Name
$object.'Name'
$value = 'Name'
$object.$value
Nézzünk egy példát arra, hogyan lehet egy meglévő hashes táblázatot objektummá alakítani:
$hash = @{'Name'='Ivan Danko'; 'City'='Moscow'; 'Country'='Russia'}
$hash.GetType()
$object = [pscustomobject]$hash
$object.GetType()

Ezeknek a típusú objektumoknak az egyik hátránya, hogy a tulajdonságaik sorrendje megváltozhat. Ennek elkerülésére az [ordered] attribútumot kell használni:
$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
További lehetőségek is vannak objektum létrehozására: fentebb a parancsmag használatát vizsgáltuk . Más dolgokat kell még megértenünk az elemek hozzáadásáról és eltávolításáról. Az előző példából származó objektum esetében ez meglehetősen egyszerű:
$object | Add-Member –MemberType NoteProperty –Name Age –Value 33
$object | Get-Member

Az Add-Member parancsmag segítségével az eddig létrehozott objektumhoz nemcsak tulajdonságokat, hanem módszereket is hozzáadhatunk az "-MemberType ScriptMethod" konstrukció használatával:
$ScriptBlock = {
# kód
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member
Vegyük észre: az új metódus kódjának tárolásához $ScriptBlock nevű ScriptBlock típusú változót használtunk.

A tulajdonságok eltávolítása a megfelelő módszerrel történik:
$object.psobject.properties.remove('Name')
Creating your own classes
A PowerShell 5.0-ban megjelent a lehetőség, hogy az objektum-orientált programozási nyelvekre jellemző szintaxis használatával. Ehhez a 'Class' kulcsszó van fenntartva, amely után meg kell adni az osztály nevét és leírni a testét kapcsos zárójelek között:
class MyClass
{
# az osztály teste
}
Ez egy valódi .NET Core típus, amelynek testében a tulajdonságait, metódusait és egyéb elemeit írjuk le. Nézzük meg a legegyszerűbb osztály definíciójának példáját:
class MyClass
{
[string]$Name
[string]$City
[string]$Country
}
Egy objektum (osztály példány) létrehozásához a következő parancsot kell használni: , vagy a [MyClass] típus literálját és new (alapértelmezett konstruktor):
$object = New-Object -TypeName MyClassvagy
$object = [MyClass]::new()Elemezzük az objektum szerkezetét:
$object | Get-Member 
Ne felejtsük el a láthatóságot: nem hivatkozhatunk a típus nevére sztringként, és nem használhatjuk a típus literálját azon kívül, ahol az osztály definiálva van (például a szkriptben vagy modulban), de a funkciók visszaadhatják az osztály példányait (objektumokat), amelyek kívül is hozzáférhetőek.
Az objektum létrehozása után töltsük ki tulajdonságait:
$object.Name = 'Ivan Danko'
$object.City = 'Moscow'
$object.Country = 'Russia'
$object

Megjegyezzük, hogy az osztály leírásában nemcsak a tulajdonságok típusait, hanem a default értékeiket is megadhatjuk:
class Example
{
[string]$Name = 'John Doe'
}
A metódus leírása hasonlít a függvény leírásához, de a 'function' kulcsszó használata nélkül. A függvényekhez hasonlóan a metódusokhoz is szükség szerint paraméterek adhatók át:
class MyClass
{
[string]$Name
[string]$City
[string]$Country
#a metódus leírása
Smile([bool]$param1)
{
If($param1) {
Write-Host ':)'
}
}
}
Most már osztályunk képviselője tud mosolyogni:
$object = [MyClass]::new()
$object.Smile($true)
A metódusokat lehet túlterhelni, ráadásul az osztályok rendelkezhetnek , valamint a nevük egyezik az osztály nevével. A PowerShell szkriptben vagy modulban definiált osztály alapként szolgálhat egy másik számára — így valósul meg az öröklés. A meglévő .NET osztályokat is elfogadjuk alapként:
class MyClass2 : MyClass
{
# az új osztály test, amelynek alapja a MyClass
}
[MyClass2]::new().Smile($true)
A PowerShell objektumokkal való munka leírását nehezen lehet kimerítőnek nevezni. A következő publikációkban gyakorlati példákon próbáljuk mélyebben bemutatni: az ötödik ciklus cikk a PowerShell harmadik féltől származó szoftverkomponensekkel való integrációval foglalkozik. A korábbi részeket az alábbi hivatkozások alatt találhatja meg.
Forrás: habr.com
