Seriál Windows PowerShell: Tvorba vlastních objektů (část 27.)
V minulém díle jsme vytvářeli textový výstup pomocí operátoru formátování. Dnes se podíváme na opačný pól – vytvoříme si vlastní objekt z daného textového výstupu.
Již několikrát jsem zmiňoval, že PowerShell je postaven nad objekty a s objekty dokáže velice efektivně pracovat. Problém občas nastává, pokud vytváříte vlastní skript nebo funkci a na výstupu chcete mít vlastní objekty. V tomto případě se hodí cmdlet New-Object. Tento cmdlet má jeden povinný parametr, TypeName, tento parametr určuje typ objektu – ve většině našich případů zde zadejte PSObject. Tím vytvoříte objekt typu System.Management.Automation.PSCustomObject – bohužel vytvoření objektu bez vlastností nebo metod nedává moc smysl:
PS C:\> New-Object -TypeName PSObject
PS C:\> $a = New-Object -TypeName PSObject
PS C:\> $a
PS C:\> $a.GetType().FullName
System.Management.Automation.PSCustomObject
PS C:\> $a | Get-Member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
K tomuto objektu můžeme vlastnosti přidávat později za běhu skriptu, například takto:
[20]: $a = $a | Add-Member -MemberType NoteProperty -Name Vlastnost -Value 'Nejaky text' -PassThru
[21]: $a
Vlastnost
---------
Nejaky text
[22]: $a | Get-Member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Vlastnost NoteProperty System.String Vlastnost=Nejaky text
Pomocí cmdletu Add-Member jsme k původnímu objektu přidali vlastnost Vlastnost a přiřadili jsme jí určitou hodnotu. I když je tento způsob vytváření objektů možný, existuje naštěstí lepší volba. Tou je použití parametru Parameter při vytváření objektu pomocí New-Object. Pojďme si vytvořit nový objekt:
PS C:\> New-Object -TypeName PSObject -Property @{ a=1; b=2; c=3 }
a b c
- - -
1 2 3
PS C:\> $b = New-Object -TypeName PSObject -Property @{ a=1; b=2; c=3 }
PS C:\> $b | Get-Member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
a NoteProperty System.Int32 a=1
b NoteProperty System.Int32 b=2
c NoteProperty System.Int32 c=3
Parameter očekává hash tabulku, jejíž dvojice klíč-hodnota se stanou vlastností a její hodnotou v novém objektu. Hash tabulku si samozřejmě můžeme vytvořit předem a pak ji uvést jako hodnotu parametru.
PS C:\> $prop = @{
>> a=1
>> b=2
>> c=3
>> }
>>
PS C:\> $prop
Name Value
---- -----
a 1
b 2
c 3
PS C:\> $prop.GetType().FullName
System.Collections.Hashtable
PS C:\> New-Object -TypeName PSObject -Property $prop
a b c
- - -
1 2 3
Vidíte, že tvorba nového objektu proběhla ve dvou krocích. Nejdříve jsme v hash tabulce určili, jaké vlastnosti bude nový objekt obsahovat a ve druhém kroku jsme tyto vlastnosti použili při vytváření objektu typu PSObject. Tím jsme si oddělili „starosti“ s přemýšlením o vlastnostech objektu. Zkusme jednoduchý příklad.
function Get-TNObject
{
param(
$ComputerName = $env:COMPUTERNAME
)
$os = Get-WmiObject -ComputerName $ComputerName -Class Win32_OperatingSystem
$prop = @{
ComputerName = $ComputerName
OSName = $os.Caption
OSVersion = $os.Version
ScanTime = Get-Date
}
New-Object -TypeName PSObject -Property $prop
}
Funkce Get-TNObject očekává na vstupu jméno počítače, který testujeme. Uvnitř funkce zavoláme cmdlet Get-WmiObject a zjistíme informace o operačním systému. Do hash tabulky poté vložíme informace o jménu počítače, jeho operačním systému a verzi a také datum, kdy jsme tento sken spustili. Na posledním řádku poté vytváříme objekt. Tento objekt je dále pouštěn do roury a výsledky funkce tam můžeme zpracovat jiným cmdletem. Použití je následující:
PS C:\> Get-TNObject
OSVersion ScanTime OSName ComputerName
--------- -------- ------ ------------
5.1.2600 05-Jun-12 11:29:14 Microsoft Windows XP Profe... MAKOVEC-40
PS C:\> Get-TNObject localhost
OSVersion ScanTime OSName ComputerName
--------- -------- ------ ------------
5.1.2600 05-Jun-12 11:29:18 Microsoft Windows XP Profe... localhost
PS C:\> Get-TNObject localhost | Format-Table -AutoSize
OSVersion ScanTime OSName ComputerName
--------- -------- ------ ------------
5.1.2600 05-Jun-12 11:29:32 Microsoft Windows XP Professional localhost
Pokud bychom chtěli zpracovávat více počítačů, můžeme použít například cmdlet ForEach-Object.
PS C:\> 'localhost',$env:COMPUTERNAME,'makovec-40','192.168.100.100' |% { Get-TNObject $_; Sleep 2 }
OSVersion ScanTime OSName ComputerName
--------- -------- ------ ------------
5.1.2600 05-Jun-12 11:34:59 Microsoft Windows XP Profe... localhost
5.1.2600 05-Jun-12 11:35:01 Microsoft Windows XP Profe... MAKOVEC-40
5.1.2600 05-Jun-12 11:35:03 Microsoft Windows XP Profe... makovec-40
5.1.2600 05-Jun-12 11:35:05 Microsoft Windows XP Profe... 192.168.100.100
Pro kontrolu jsem přidal čekání dvě vteřiny, aby bylo vidět, že ScanTime se nám opravdu mění v závislosti na volání funkce. Jak jsem již zmiňoval – výstupem jsou objekty a můžeme s nimi dále libovolně pracovat.
PS C:\> 'localhost',$env:COMPUTERNAME, 'makovec-40','192.168.100.100' |% { Get-TNObject $_ } | Sort ComputerName
OSVersion ScanTime OSName ComputerName
--------- -------- ------ ------------
5.1.2600 05-Jun-12 11:38:28 Microsoft Windows XP Profe... 192.168.100.100
5.1.2600 05-Jun-12 11:38:28 Microsoft Windows XP Profe... makovec-40
5.1.2600 05-Jun-12 11:38:28 Microsoft Windows XP Profe... MAKOVEC-40
5.1.2600 05-Jun-12 11:38:28 Microsoft Windows XP Profe... localhost
PS C:\> 'localhost',$env:COMPUTERNAME, 'makovec-40','192.168.100.100' |% { Get-TNObject $_ } | Sort ComputerName | ft -AutoSize
OSVersion ScanTime OSName ComputerName
--------- -------- ------ ------------
5.1.2600 05-Jun-12 11:38:43 Microsoft Windows XP Professional 192.168.100.100
5.1.2600 05-Jun-12 11:38:43 Microsoft Windows XP Professional makovec-40
5.1.2600 05-Jun-12 11:38:43 Microsoft Windows XP Professional MAKOVEC-40
5.1.2600 05-Jun-12 11:38:43 Microsoft Windows XP Professional localhost
Tato technika vytváření objektů za běhu funkce nebo skriptu je velice užitečná. Vzhledem k tomu, že v PowerShellu pracujeme s objekty velice často, byla by škoda, pokud by vaše funkce/skripty pouze posílaly textový výstup pomocí Write-Host. Až budete příště zpracovávat nějaká data, vzpomeňte si na New-Object a zkuste jej využít.
- David Moravec