Shfaqja tekstuale e komandave në dritaren e interpretuese PowerShell është thjesht një mënyrë për të paraqitur informacionin në një format të kuptueshëm për njerëzit. Në fakt, mjedisi për punimin me objekte: komandlet dhe funksionet i pranojnë ata si input dhe , ndërsa tipet e ndryshoreve që janë të disponueshme në modin interaktiv dhe në skriptet bazohen në klasat .NET. Në artikullin e katërt të ciklit ne do të shqyrtojmë punimin me objekte më në detaje.
Përmbajtje:
Objektet në PowerShell
Le të kujtojmë se një objekt është një grumbull fushash të dhënash (pronash, ngjarjesh, etj.) dhe mënyrash për përpunimin e tyre (metodash). Struktura e tij përcaktohet nga tipi, i cili zakonisht bazohet në klasat që përdoren në platformën e unifikuar .NET Core. Po ashtu ka mundësi për të punuar me objekte COM, CIM (WMI) dhe ADSI. Pronat dhe metodat janë të nevojshme për të kryer veprime të ndryshme mbi të dhënat, përveç kësaj, në PowerShell, objektet mund të kalohen si argumente në funksione dhe komandlet, të caktohen vlerat e tyre në variabla, dhe gjithashtu ekziston (kanali ose pipeline). Çdo komandë në kanalin kalon daljen e saj te komandë tjetër njëra pas tjetrës — objekt pas objekti. Për përpunimin mund të përdoren komandlet e përgatitura ose të krijohen , për të kryer manipulime të ndryshme me objektet në kanalin: filtrimin, renditjen, grupimin dhe madje edhe ndryshimin e strukturës së tyre. Kalimi i të dhënave në këtë formë ka një avantazh të konsiderueshëm: ekipi që merr informacionin nuk ka nevojë të merret me analizimin sintaksor të mjedisit të bytes (tekstit), të gjitha informacionet e nevojshme nxirren lehtësisht përmes hyrjeve në pronat dhe metodat përkatëse.
Shikimi i strukturës së objekteve
Për shembull, le të ekzekutojmë komandlet Get-Process, e cila lejon të merrni informacion mbi proceset që janë aktive në sistem:

Ai do të shfaqë disa të dhëna të formatizuara tekstuale, që nuk japin një ide të qartë mbi pronat e objekteve të kthyer dhe metodat e tyre. Për të analizuar më në detaje daljen, është e nevojshme të mësojmë të hetojmë strukturën e objekteve dhe këtu do të na ndihmojë komandleti Get-Member:
Get-Process | Get-Member 
Këtu tashmë shohim llojin dhe strukturën, dhe duke përdorur parametra shtesë, mund të shfaqim vetëm pronat e objekteve që kalojnë përmes:
Get-Process | Get-Member -MemberType PropertyKëto njohuri do të nevojiten për të zgjidhur detyra administrimi në mënyrë interaktive ose për të shkruar skriptet tuaja: thjesht, për të marrë informacione mbi proceset e pezulluara sipas pronës Responding.
Filtrimi i objekteve
PowerShell lejon që objekteve që përmbushin një kusht të caktuar t'u kalohen përmes tubit:
Where-Object { blloku i skenarit }Rezultati i ekzekutimit të bllokut të skenarit në kllapa duhet të jetë një vlerë logjike. Nëse është e vërtetë ($true), objekti i kaluar në komandletin Where-Object do të kalojë më tej përmes tubit, ndryshe (vlera $false) do të hiqet. Për shembull, le të shfaqim listën e shërbimeve të ndaluara të Windows Server, pra ato për të cilat prona Status ka vlerën "Stopped":
Get-Service | Where-Object {$_.Status -eq "Stopped"} 
Këtu sërish shohim një përfaqësim tekstual, por nëse dëshirojmë të kuptojmë llojin dhe strukturën e brendshme të objekteve që kalojnë nëpër tub, nuk është e vështirë:
Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member 
Renditja e objekteve
Gjatë përpunimit të objekteve nëpërmjet tubit, shpesh ndodhet nevoja për t'i renditur ato. Tek komandleti Sort-Object kalohen emrat e pronave (çelësat e renditjes), dhe ai kthen objekte të renditura sipas vlerave të tyre. Dalja e proceseve të nisura mund të renditet lehtësisht sipas kohës së shpenzuar të procesorit (prona cpu):
Get-Process | Sort-Object –Property cpuParametri -Property kur thirret komandleti Sort-Object mund të mos specifikohet — ai përdoret si standard. Për renditjen në të kundërt, përdoret параметri -Descending:
Get-Process | Sort-Object cpu -Descending 
Shkëputja e objekteve dhe pjesëve të tyre
Komandleti Select-Object lejon të zgjidhet një numër i caktuar objektesh në fillim ose në fund të tubit duke përdorur parametrat -First ose -Last. Me të mund të zgjidhni objekte individuale ose prona të caktuara, si dhe të krijoni objekte të reja mbi bazën e tyre. Le të shqyrtojmë funksionimin e komandletit me disa shembuj të thjeshtë.
Komanda e mëposhtme shfaq informacione për 10 proceset që konsumojnë maksimumin e memories (prona WS):
Get-Process | Sort-Object WS -Descending | Select-Object -First 10 
Mund të ngushtojmë vetëm pronat e caktuara të objekteve që kalojnë përmes tubit dhe të krijojmë të reja mbi bazën e tyre:
Get-Process | Select-Object ProcessName, Id -First 1Si rezultat i punës së tubit, do të marrim një objekt të ri, struktura e të cilit do të jetë e ndryshme nga struktura e kthyer nga komandleti Get-Process. Le të sigurohemi për këtë duke përdorur Get-Member:
Get-Process | Select-Object ProcessName, Id -First 1 | Get-Member 
Vini re se Select-Object kthën një objekt të vetëm (-First 1), i cili ka vetëm dy fushat që ne kemi specifikuar: vlerat e tyre janë kopjuar nga objekti i parë që iu dha tubit komandleti Get-Process. Një nga mënyrat e krijimit të objekteve në skenarët PowerShell bazohet në përdorimin e Select-Object:
$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType() 
Me ndihmën e Select-Object, mund të shtoni prona të llogaritura për objekte, të cilat duhen paraqitur si . Në këtë rast, vlera e çelësit të saj të parë përputhet me emrin e pronës, ndërsa vlera e dytë është vlera e pronës për elementin aktual të tubit:
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} 
Le të shohim strukturën e objekteve që kalojnë përmes tubit:
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} | Get-Member 
ForEach-Object, Group-Object dhe Measure-Object
Për punën me objektet ekzistojnë edhe komandlete të tjera. Si shembull, do të flasim për tre më të dobishme:
ForEach-Object lejon të ekzekutoni kod në gjuhën PowerShell për çdo objekt në tub:
ForEach-Object { blloku i skenarit }Group-Object grupon objekte sipas vlerës së pronës:
Group-Object PropertyNameNëse e ekzekutoni me parametrin -NoElement, mund të mësoni numrin e elementeve në grupe.
Measure-Object agregon parametra të ndryshëm përmbledhës sipas vlerave të fushave të objekteve në tub (llogarit shumën, si dhe gjen vlerat minime, maksimale ose mesatare):
Measure-Object -Property PropertyName -Minimum -Maximum -Average -SumNormalisht, komandlet e shqyrtuara përdoren në mod të ndërveprimit, ndërsa në skenarë shpesh krijohen me blloqe Begin, Process dhe End.
Krijimi i objekteve .NET dhe COM (New-Object)
Ka njohim shumë komponente programore me ndërfaqe .NET Core dhe COM, të cilat janë të dobishme për administratoret e sistemeve. Duke përdorur klasën System.Diagnostics.EventLog, mund të menaxhoni regjistrat e sistemeve drejtpërdrejt nga Windows PowerShell. Le të shqyrtojmë një shembull të krijimit të një instancë të kësaj klase duke përdorur komandën New-Object me parametrin -TypeName:
New-Object -TypeName System.Diagnostics.EventLog 
Pasi nuk kemi specifikuar një regjistër ngjarjesh të caktuar, instanca e marrë e klasës nuk përmban të dhëna. Për të ndryshuar këtë, është e nevojshme që gjatë krijimit të saj të thërrasim një metodë ndihmëse përmes parametrin -ArgumentList. Nëse dëshirojmë të qasemi në regjistrin e aplikacioneve, duhet të kalojmë në konstruktor stringun "Application" si argument:
$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog 
Vini re: të dhënat e komandës i ruajmë në variablin $AppLog. Megjithëse në modalitetin ndërveprues zakonisht përdoren tubacione, shkruanja e skenarëve shpesh kërkon ruajtjen e një lidhjeje me objektin. Për më tepër, klasat kryesore .NET Core gjenden në hapësirën e emrave System: PowerShell në mënyrë të paracaktuar i kërkon aty llojet e shënuara, kështu që shkruarja e Diagnostics.EventLog në vend të System.Diagnostics.EventLog është plotësisht e saktë.
Për të punuar me regjistrin, mund të qasemi në metodat përkatëse:
$AppLog | Get-Member -MemberType Method 
Të themi se ai pastruar me metodën Clear() nëse kemi të drejtat e nevojshme:
$AppLog.Clear()Komanda New-Object përdoret gjithashtu për të punuar me komponentët COM. Ka shumë prej tyre — nga skriptet e ofruara me serverin në bibliotekat e Windows, deri te aplikacionet ActiveX, si Internet Explorer, për shembull. Për të krijuar një objekt COM, kërkohet të specifikohet parametri -ComObject me identifikatorin e klasësProgId të nevojshme:
New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObjectPër të krijuar objekte të veta me strukturë të rastësishme, përdorimi i New-Object duket shumë i vjetër dhe i rëndë; ky komandë është përdorur për të punuar me komponentë programorë të jashtëm në raport me PowerShell. Në artikujt në vazhdim do të shqyrtojmë këtë çështje më në detaje. Përveç objekteve .NET dhe COM, ne gjithashtu do të studiojmë objektet CIM (WMI) dhe ADSI.
Thirrja e metodave statike
Nuk është e mundur të krijohen instanca të disa klasave të .NET Core: kjo përfshin System.Environment dhe System.Math. Ato janë dhe përmbajnë vetëm pasuri dhe metoda statike. Në thelb, këto janë biblioteka referuese që përdoren pa krijuar objekte. Të referoheni në një klasë statike mund të bëhet përmes një literal, duke e rrethuar emrin e tipit me katrorë. Kur të shohim strukturën e objektit duke përdorur Get-Member, ne do të shohim tipin System.RuntimeType në vend të System.Environment:
[System.Environment] | Get-Member 
Për të parë vetëm elementet statike, duhet të thërrasësh Get-Member me parametrin -Static (vini re tipin e objektit):
[System.Environment] | Get-Member -Static 
Për të aksesuar pasuritë dhe metodat statike përdoren dy dy pika një pas tjetres në vend të pikës pas literalit:
[System.Environment]::OSVersionИли
$test=[System.Math]::Sqrt(25)
$test
$test.GetType() 
Tipi PSCustomObject
Mes numrit të madh të tipave të dhënave të disponueshëm në PowerShell, një vlen të përmendet veçanërisht, PSCustomObject, e krijuar për ruajtjen e objekteve me strukturë të rastësishme. Krijimi i një objekti të tillë me ndihmën e komandletit New-Object konsiderohet si një metodë klasike, por e sofistikuar dhe e vjetruar:
$object = New-Object –TypeName PSCustomObject -Property @{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'}
Të shohim strukturën e objektit:
$object | Get-Member 
Duke filluar nga PowerShell 3.0, gjithashtu është në dispozicion një sintaksë tjetër:
$object = [PSCustomObject]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Qasja në të dhënat mund të bëhet në një nga mënyrat ekuivalente:
$object.Name
$object.'Name'
$value = 'Name'
$object.$value
Le të japim një shembull të konvertimit në një objekt të një hash tabule ekzistuese:
$hash = @{'Name'='Ivan Danko'; 'City'='Moscow'; 'Country'='Russia'}
$hash.GetType()
$object = [pscustomobject]$hash
$object.GetType()

Një nga disavantazhet e objekteve të këtij tipi është se rendi i pronave të tyre mund të ndryshojë. Për të shmangur këtë, është e nevojshme të përdoret atributi [ordered]:
$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Ka edhe variante të tjera për krijimin e objektit: ne shqyrtuam përdorimin e komandletit . Tani mbetet të kuptojmë se si të shtojmë dhe heqim elemente. Për të bërë këtë për objektin nga shembulli i mëparshëm është e thjeshtë:
$object | Add-Member –MemberType NoteProperty –Name Age –Value 33
$object | Get-Member

Komandleti Add-Member lejon të shtosh jo vetëm pasuri, por gjithashtu metoda në objektin e krijuar $object duke përdorur konstrukcionin "-MemberType ScriptMethod":
$ScriptBlock = {
# kod
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member
Vini re në vëmendje: për të ruajtur kodin e metodës së re, ne përdorëm një variabël $ScriptBlock të tipit ScriptBlock.

Për të fshirë pronat, përdoret metoda përkatëse:
$object.psobject.properties.remove('Name')
Krijimi i klasave tona
Në PowerShell 5.0 u bë e mundur të përcaktohen duke përdorur sintaksën tipike për gjuhët e programimit objekt-orientuar. Për këtë qëllim është fjala kyçe Class, pas së cilës duhen caktuar emri i klasës dhe përshkruhet trupi i saj në kllapa operatorike:
class MyClass
{
# trupi i klasës
}
Ky është një tip i vërtetë .NET Core, në trupin e të cilit përshkruhen pronat, metodat dhe elementë të tjerë. Le të shohim një shembull të përcaktimit të një klase më të thjeshtë:
class MyClass
{
[string]$Name
[string]$City
[string]$Country
}
Për të krijuar një objekt (ekzemplar klase) përdoret komandleti , ose literal i tipit [MyClass] dhe new (konstruktori i paracaktuar):
$object = New-Object -TypeName MyClassили
$object = [MyClass]::new()Le të analizojmë strukturën e objektit:
$object | Get-Member 
Nuk duhet harruar rreth fushës së dukshmërisë: nuk mund të referoheni emrit të tipit si varg ose të përdorni literalin e tipit jashtë skenarit ose modulit ku është përcaktuar klasa. Në këtë rast, funksionet mund të kthejnë ekzemplarë klase (objekte) që do të jenë të disponueshme jashtë modulit ose skenarit.
Pas krijimit të objektit, le të mbushim pronat e tij:
$object.Name = 'Ivan Danko'
$object.City = 'Moscow'
$object.Country = 'Russia'
$object

Vlen të theksohet se në përshkrimin e klasës përcaktohen jo vetëm tipet e pronave, por edhe vlerat e tyre të paracaktuara:
class Example
{
[string]$Name = 'John Doe'
}
Përshkrimi i metodës së klasës është i ngjashëm me përshkrimin e funksionit, por pa përdorimin e fjalës kyçe function. Ashtu si te funksioni, në metodat, kur është e nevojshme, kalohen parametra:
class MyClass
{
[string]$Name
[string]$City
[string]$Country
#përshkrimi i metodës
Smile([bool]$param1)
{
If($param1) {
Write-Host ':)'
}
}
}
Tani përfaqësuesi i klasës sonë di të buzëqeshë:
$object = [MyClass]::new()
$object.Smile($true)
Metodat mund të tejkalohen, për më tepër klasa ka , si gjithashtu ndërtuesit, emrat e të cilëve përputhen me emrin e klasës vetë. Një klasë e caktuar në një skenar ose modul PowerShell mund të shërbejë si bazë për një tjetër — kështu realizohet trashëgimia. Në këtë rast, është e pranueshme përdorimi i klasave ekzistuese .NET si klasat themelore:
class MyClass2 : MyClass
{
#trupi i klasës së re, e cila është bazë për MyClass
}
[MyClass2]::new().Smile($true)
Përshkrimi ynë mbi punën me objektet në PowerShell është e vështirë të quhet e plotë. Në publikimet në vazhdim, do të përpiqemi ta thellojmë atë me shembuj praktikë: artikulli i pestë i ciklit do t'i kushtohet pyetjeve mbi integrimin e PowerShell me komponentë të jashtëm programorë. Pjesët e kaluara mund të gjenden në lidhjet më poshtë.
Burimi: habr.com
