Tekstualni izlaz naredbi u prozoru PowerShell interpreter je samo način prikazivanja informacija na ljudski razumljiv način. U stvarnosti, okruženje na rad s objektima: cmdleti i funkcije ih primaju kao ulaz i , a tipovi varijable dostupni u interaktivnom režimu i u skriptama temelje se na .NET klasama. U četvrtom članku ciklusa proučit ćemo rad s objektima detaljnije.
Sadržaj:
Objekti u PowerShell-u
Podsjetimo se, objekt je skup podataka (svojstava, događaja itd.) i načina njihove obrade (metoda). Njegova struktura određena je tipom, koji se obično temelji na klasama korištenim u unificiranoj .NET Core platformi. Također, postoji mogućnost rada s COM, CIM (WMI) i ADSI objektima. Svojstva i metode su potrebni za izvršavanje različitih radnji na podacima, osim toga, u PowerShell-u se objekti mogu proslijediti kao argumenti funkcijama i cmdletima, dodijeliti njihove vrijednosti varijablama, a postoji i (cjevovod ili pipeline). Svaka naredba u cjevovodu prosljeđuje svoj izlaz sljedećoj redom — objekt po objekt. Za obradu se mogu koristiti kompajlirani cmdleti ili stvoriti vlastite , kako bi se izvodile različite manipulacije s objektima u cjevovodu: filtriranje, sortiranje, grupiranje i čak mijenjanje njihove strukture. Prosljeđivanje podataka na ovaj način ima značajnu prednost: primateljskoj naredbi nije potrebno obavljati sintaktičku analizu toka bajtova (teksta), sve potrebne informacije lako se izvlače pozivanjem odgovarajućih svojstava i metoda.
Pregled strukture objekata
Na primjer, pokrenut ćemo cmdlet Get-Process, koji omogućuje dobivanje informacija o procesima koji rade u sustavu:

On će prikazati određene formatirane tekstualne podatke koji ne daju uvid u svojstva vraćenih objekata i njihove metode. Kako bismo bolje analizirali izlaz, potrebno je naučiti istraživati strukturu objekata, a u tome će nam pomoći cmdlet Get-Member:
Get-Process | Get-Member 
Ovdje već vidimo tip i strukturu, a dodatnim parametrima možemo, na primjer, izlistati samo svojstva objekta koji je unesen:
Get-Process | Get-Member -MemberType PropertyOva znanja će biti korisna za rješavanje administrativnih zadataka u interaktivnom režimu ili za pisanje vlastitih skripti: recimo, kako bismo dobili informacije o zaustavljenim procesima prema svojstvu Responding.
Filtriranje objekata
PowerShell omogućuje prosljeđivanje objekata koji ispunjavaju određeni uvjet kroz cjevovod:
Where-Object { blok skripte }Rezultat izvršenja bloka skripte u vitičastim zagradama treba biti logička vrijednost. Ako je ona istinita ($true), objekat koji ulazi u cmdlet Where-Object bit će proslijeđen dalje kroz cjevovod; u suprotnom (vrijednost $false) bit će uklonjen. Na primjer, izlistajmo popis zaustavljenih usluga Windows Server, tj. onih čije svojstvo Status ima vrijednost 'Stopped':
Get-Service | Where-Object {$_.Status -eq "Stopped"} 
Ovdje ponovo vidimo tekstualni prikaz, ali nije teško razumjeti tip i unutarnju strukturu objekata koji prolaze kroz cjevovod:
Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member 
Sortiranje objekata
Prilikom obrade objekata kroz cjevovod često se javlja potreba za njihovim sortiranjem. U cmdlet Sort-Object prenose se imena svojstava (ključevi sortiranja), a on vraća objekte sortirane prema njihovim vrijednostima. Izlaz pokrenutih procesa može se lako sortirati prema utrošenom procesorskom vremenu (svojstvo cpu):
Get-Process | Sort-Object –Property cpuParametar -Property prilikom pozivanja cmdleta Sort-Object može se ne navesti — koristi se prema zadanim postavkama. Za obrnutu sortaciju koristi se parametar -Descending:
Get-Process | Sort-Object cpu -Descending 
Isticanje objekata i njihovih dijelova
Cmdlet Select-Object omogućuje izdvajanje određenog broja objekata na početku ili na kraju cjevovoda pomoću parametara -First ili -Last. Uz njegovu pomoć možete izabrati pojedinačne objekte ili određena svojstva, a također stvoriti nove objekte temeljem njih. Razmotrit ćemo rad cmdleta kroz jednostavne primjere.
Sljedeća naredba ispisuje informacije o 10 procesa koji koriste najviše RAM-a (svojstvo WS):
Get-Process | Sort-Object WS -Descending | Select-Object -First 10 
Možete odabrati samo određena svojstva objekata koji prolaze kroz cjevovod i na njihovoj osnovi stvoriti nove:
Get-Process | Select-Object ProcessName, Id -First 1Kao rezultat rada cjevovoda dobit ćemo novi objekt čija će struktura biti drugačija od strukture vraćene naredbom Get-Process. Provjerimo to pomoću Get-Member:
Get-Process | Select-Object ProcessName, Id -First 1 | Get-Member 
Imajte na umu da Select-Object vraća pojedinačni objekt (-First 1), koji ima samo prepoznate dva polja: njihove su vrijednosti kopirane iz prvog objekta koji je poslan u cjevovod naredbom Get-Process. Korištenje Select-Object-a je jedan od načina za stvaranje objekata u PowerShell skriptama:
$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType() 
Uz Select-Object možete dodati izračunate atribute objektima koje treba prikazati u obliku . Pri tome vrijednost njenog prvog ključa odgovara imenu svojstva, a vrijednost drugog — vrijednosti svojstva za trenutni element cjevovoda:
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} 
Pogledajmo strukturu objekata koji prolaze kroz cjevovod:
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} | Get-Member 
ForEach-Object, Group-Object i Measure-Object
Postoje i druge naredbe za rad s objektima. Kao primjer, govorit ćemo o tri najkorisnija:
ForEach-Object omogućuje izvršavanje koda u PowerShell-u za svaki objekt u cjevovodu:
ForEach-Object { blok skripta }Group-Object grupira objekte prema vrijednosti svojstva:
Group-Object PropertyNameAko ga pokrenete s parametrom -NoElement, možete saznati broj elemenata u grupama.
Measure-Object agregira različite sažetke parametara prema vrijednostima polja objekata u cjevovodu (izračunava sumu, kao i nalaz minimalne, maksimalne ili prosječne vrijednosti):
Measure-Object -Property PropertyName -Minimum -Maximum -Average -SumObično se razmotreni cmdleti koriste u interaktivnom načinu, dok se u skriptama češće stvaraju s blokovima Begin, Process i End.
Izrada .NET i COM objekata (New-Object)
Postoji mnoštvo softverskih komponenti s .NET Core i COM sučeljima koje će pomoći sistemskim administratorima. Pomoću klase System.Diagnostics.EventLog možete upravljati sistemskim dnevnicima direktno iz Windows PowerShell-a. Razmotrit ćemo primjer stvaranja instance ove klase pomoću cmdleta New-Object s parametrima -TypeName:
New-Object -TypeName System.Diagnostics.EventLog 
Budući da nismo naveli određeni dnevnik događaja, dobivena instanca klase ne sadrži podatke. Da bismo to promijenili, prilikom stvaranja potrebno je pozvati poseban konstruktor s parametrima -ArgumentList. Ako želimo pristupiti dnevniku aplikacija, konstruktoru treba proslijediti string „Application“ kao argument:
$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog 
Napomena: izlazne podatke komande sačuvali smo u varijabli $AppLog. Iako se u interaktivnom režimu obično koriste cijevi, pisanje skripta često zahtijeva čuvanje reference na objekt. Osim toga, osnovne klase .NET Core nalaze se u prostoru imena System: PowerShell prema zadanim postavkama traži navedene tipove u njemu, stoga je pisanje Diagnostics.EventLog umjesto System.Diagnostics.EventLog sasvim ispravno.
Za rad s dnevnikom možete koristiti odgovarajuće metode:
$AppLog | Get-Member -MemberType Method 
Recimo, briše se metodom Clear() uz uvjet da su prava pristupa odobrena:
$AppLog.Clear()Cmdlet New-Object se također koristi za rad s COM komponentama. Ima ih prilično mnogo — od SCRIPT biblioteka isporučenih s poslužiteljem do ActiveX aplikacija, poput Internet Explorera. Da biste stvorili COM objekt, potrebno je navesti parametar -ComObject s programski identifikatorom ProgId željene klase:
New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObjectZa stvaranje vlastitih objekata s proizvoljnom strukturom korištenje New-Object izgleda previše arhaično i složeno; ovaj cmdlet se koristi za rad s vanjskim programskim komponentama u odnosu na PowerShell. U sljedećim člancima tematika će biti detaljnije obrađena. Osim .NET i COM objekata, također ćemo proučiti CIM (WMI) i ADSI objekte.
Pozivanje statičkih metoda
Instance nekih .NET Core klasa nije moguće stvoriti: među njih spadaju System.Environment i System.Math. One su i sadrže samo statičke osobine i metode. U suštini, to su referentne biblioteke koje se koriste bez kreiranja objekata. Na statičku klasu se može pozvati kroz literale, stavljajući ime tipa u uglate zagrade. U tom slučaju, ako pogledamo strukturu objekta pomoću Get-Member, vidjet ćemo tip System.RuntimeType umjesto System.Environment:
[System.Environment] | Get-Member 
Da bismo vidjeli samo statičke elemente, potrebno je pozvati Get-Member s parametrom -Static (obratite pažnju na tip objekta):
[System.Environment] | Get-Member -Static 
Za pristup statičkim osobinama i metodama koriste se dva dvotačke umjesto točke nakon literala:
[System.Environment]::OSVersionIli
$test=[System.Math]::Sqrt(25)
$test
$test.GetType() 
Tip PSCustomObject
Među brojnim dostupnim tipovima podataka u PowerShellu, posebno se ističe PSCustomObject, namijenjen za pohranu objekata s proizvoljnom strukturom. Kreiranje takvog objekta pomoću cmdlet-a New-Object smatra se klasičnim, ali opterećujućim i zastarjelim načinom:
$object = New-Object –TypeName PSCustomObject -Property @{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'}
Pogledajmo strukturu objekta:
$object | Get-Member 
Počevši od PowerShell 3.0, dostupan je i drugi sintaktički oblik:
$object = [PSCustomObject]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Podacima možemo pristupiti na jedan od ekvivalentnih načina:
$object.Name
$object.'Name'
$value = 'Name'
$object.$value
Dajmo primjer pretvaranja u objekt postojeće hash tablice:
$hash = @{'Name'='Ivan Danko'; 'City'='Moscow'; 'Country'='Russia'}
$hash.GetType()
$object = [pscustomobject]$hash
$object.GetType()

Jedna od nedostataka objekata ovog tipa je da se redoslijed njihovih osobina može promijeniti. Da bismo to izbjegli, potrebno je koristiti atribut [ordered]:
$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Postoje i druge mogućnosti kreiranja objekta: gore smo razmotrili korištenje cmdlet-a . Ostalo je da se razjasnimo oko dodavanja i brisanja elemenata. To za objekt iz prethodnog primjera može biti prilično jednostavno:
$object | Add-Member –MemberType NoteProperty –Name Age –Value 33
$object | Get-Member

Cmdlet Add-Member omogućava dodavanje ranije kreiranom objektu $object ne samo svojstava, već i metoda pomoću konstrukcije "-MemberType ScriptMethod":
$ScriptBlock = {
# kod
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member
Napomena: za pohranu koda nove metode koristili smo varijablu $ScriptBlock tipa ScriptBlock.

Za uklanjanje svojstava koristi se odgovarajuća metoda:
$object.psobject.properties.remove('Name')
Izrada vlastitih klasa
U PowerShell 5.0 uvedena je mogućnost definiranja korištenjem sintakse specifične za objekte orijentirane jezike programiranja. Za to je namijenjena ključna riječ Class, nakon koje slijedi naziv klase i opis njenog tijela unutar vitičastih zagrada:
class MyClass
{
# tijelo klase
}
To je pravi .NET Core tip, čije tijelo opisuje njegove osobine, metode i druge elemente. Razmotrimo primjer definicije najjednostavnije klase:
class MyClass
{
[string]$Name
[string]$City
[string]$Country
}
Za stvaranje objekta (instanca klase) koristi se cmdlet , ili literal tipa [MyClass] i new (zadani konstruktor):
$object = New-Object -TypeName MyClassili
$object = [MyClass]::new()Analizirajmo strukturu objekta:
$object | Get-Member 
Ne smijemo zaboraviti na vidljivost: ne možemo se referirati na naziv tipa kao na string ili koristiti literal tipa izvan skripte ili modula u kojem je klasa definirana. U tom slučaju funkcije mogu vraćati instance klase (objekte) koje će biti dostupne izvan modula ili skripte.
Nakon stvaranja objekta popunimo njegove osobine:
$object.Name = 'Ivan Danko'
$object.City = 'Moskva'
$object.Country = 'Rusija'
$object

Napominjemo da se u opisu klase ne postavljaju samo tipovi svojstava, već i njihove zadane vrijednosti:
class Example
{
[string]$Name = 'John Doe'
}
Opis metode klase nalikuje opisu funkcije, no bez korištenja ključne riječi function. Kao i u funkciji, u metode se po potrebi prosljeđuju parametri:
class MyClass
{
[string]$Name
[string]$City
[string]$Country
#opis metode
Smile([bool]$param1)
{
If($param1) {
Write-Host ':)'
}
}
}
Sada predstavnik naše klase zna se smiješiti:
$object = [MyClass]::new()
$object.Smile($true)
Metode se mogu preopteretiti, osim toga, klase mogu imati , kao i konstruktori čija imena se poklapaju s imenom same klase. Klasa definirana u PowerShell skripti ili modulu može služiti kao osnovna za drugu — tako se ostvaruje nasleđivanje. Pri tome je dopušteno korišćenje postojećih .NET klasa kao osnovnih:
class MyClass2 : MyClass
{
#tijelo nove klase, koja je osnovna za MyClass
}
[MyClass2]::new().Smile($true)
Naš opis rada s objektima u PowerShellu teško da možemo nazvati iscrpnim. U sledećim objavama pokušaćemo ga produbiti na praktičnim primerima: peti članak ciklusa biće posvećen pitanjima integracije PowerShell-a s vanjskim softverskim komponentama. Prošli delovi se mogu naći na linkovima ispod.
Izvor: habr.com
