Seriál Windows PowerShell: Typ objektu (část 28.)

Při našem posledním předprázdninovém setkání jsme vytvářeli vlastní objekty. Dnes posuneme naši snahu o dokonalost o trochu dále. Pouze pro jistotu zopakujeme použitý kód:

function Get-TNObject 

    param
        $ComputerName = $env:COMPUTERNAME 
    )

    $os = Get-WmiObject -ComputerName $ComputerName -ClassWin32_OperatingSystem

    $prop = @{ 
        ComputerName = $ComputerName 
        OSName       = $os.Caption 
        OSVersion    = $os.Version 
        ScanTime     = Get-Date 
    }

    New-Object -TypeName PSObject -Property $prop

}

Výstupem dané funkce je například:

PS C:\> Get-TNObject | Format-Tablet -AutoSize

OSVersion ScanTime           OSName                            ComputerName 
--------- --------           ------                            ------------ 
5.1.2600  03-Sep-12 23:23:48 Microsoft Windows XP Professional MAKOVEC-40

Pokud si uložíme výstupní objekt do proměnné – se kterou chceme dále pracovat - dostaneme následující výsledky:

PS C:\> $tn = Get-TNObject

PS C:\Scripts > $tn.GetType()

IsPublic IsSerial Name           BaseType 
-------- -------- ----           -------- 
True     False    PSCustomObject System.Object

PS C:\> $tn.GetType().FullName 
System.Management.Automation.PSCustomObject

PS C:\Scripts > $tn | gm

   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() 
ComputerName NoteProperty System.String ComputerName=MAKOVEC-40 
OSName       NoteProperty System.String OSName=Microsoft Windows XP Professional 
OSVersion    NoteProperty System.String OSVersion=5.1.2600 
ScanTime     NoteProperty System.DateTime ScanTime=0š-Sep-12 23:25:46

Vidíme, že objekt typu PSCustomObject. Vzhledem k tomu, že si dnes budeme trochu hrát s typem objektu, hodilo by se nám zjistit, jak jsme se vlastně dostali k „výslednému“ typu objektu.

Pozn.: Pokud jsou mezi vámi vývojáři, promiňte prosím v rámci zjednodušení některé prohřešky proti běžným konvencím. Dopouštím se jich vědomě.

PS C:\> $tn.PSTypeNames 
System.Management.Automation.PSCustomObject 
System.Object

Pokud čteme výstup odspodu, vidíme, že náš TN objekt je zároveň typu Systém.Object (základ všech objektů v .NET) a již uvedeného PSCustomObject. Tato vlastnost se nám může hodit v případě vytváření vlastních rozšíření pomocí formátovacích souborů (o těchto souborech si povíme více v některém z příštích pokračování). Nejprve si ale musíme připravit naše objekty. Pro názornost si ještě ukážeme, jakého typu je například objekt z WMI.

PS C:\> $os = Get-WmiObject -Class Win32_OperatingSystem 
PS C:\> $os.PSTypeNames 
System.Management.ManagementObject#root\cimv2\Win32_OperatingSystem 
System.Management.ManagementObject 
System.Management.ManagementBaseObject 
System.ComponentModel.Component 
System.MarshalByRefObject 
System.Object

Vidíte, že opět začínáme u Systém.Object a pokračujeme dalšími typy až k výsledném Win32_OperatingSystem.

Přemýšleli jste někdy nad tím, proč se při zadání

PS C:\> Get-WmiObject Win32_OperatingSystem

SystemDirectory : C:\WINDOWS\system32 
Organization    : PowerShell.cz 
BuildNumber     : 2600 
RegisteredUser  : PowerShell.cz 
SerialNumber    : 12345-678-12345-678910 
Version         : 5.1.2600

zobrazí pouze pár vlastností, když jich je ve skutečnosti mnohem více?

PS C:\> Get-WmiObject Win32_OperatingSystem | Get-Member -MemberType Property | Measure-Object

Count : 71

Pro zobrazení všech hodnot můžete použít

PS C:\> Get-WmiObject Win32_OperatingSystem | Format-List -Property *

Nebudeme zde z důvodu místa uvádět výsledek – sami si ho můžete jednoduše zobrazit. Zobrazení vlastností je kontrolované právě takzvaným formátovacím souborem. Pokud si zobrazíme část tohoto souboru – právě pro WMI objekty – uvidíme toto:

image

Pokud se podíváte na část PSStandardMembers a porovnáte ji s výstupem cmdletu Get-WmiObject, uvidíte jistou shodu. Právě tato část určuje, jaké vlastnosti se zobrazí při standardním výstupu.

Pozor! Pokud neodoláte touze a soubor najdete, v žádném případě jej neměňte. Soubor je digitálně podepsán a jeho změnou si narušíte jednu ze základních funkcí PowerShellu. Existují lepší metody, jak standardní výpis změnit.

Pojďme tedy na začátek dnešního článku a zkusme si změnit (přidat) nový typ k našemu TN objektu. Osobně mám rád cestu, kdy nejdříve zrušíme veškeré informace o typu a poté přidáme pouze náš vlastní.

PS C:\> $tn.PSTypeNames 
System.Management.Automation.PSCustomObject 
System.Object

PS C:\> $tn.PSTypeNames.Clear()

PS C:\> $tn.PSTypeNames

PS C:\> $tn.PSTypeNames.Add('Makovec.TNObjekt')

PS C:\> $tn.PSTypeNames 
Makovec.TNObjekt

PS C:\> $tn | Get-Member

TypeName: Makovec.TNObjekt

Nyní máme připravený objekt pro další práci. Abychom nemuseli upravovat výsledné objekty, je lepší měnit typ ihned po vytvoření objektu. Proto si trochu upravíme původní funkci.

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 
    }

    $obj = New-Object -TypeName PSObject -Property $prop 
    $obj.PSTypeNames.Clear() 
    $obj.PSTypeNames.Add('Makovec.TNObjekt'
    
$obj

}

Při zobrazování tohoto typu objektu můžeme použít formátovací soubor. Jak již bylo uvedeno – použití tohoto souboru si ukážeme v některém z příštích pokračování.

Příště se podíváme na PowerShell v3 – vzhledem k tomu, že uvedení Win8 se blíží, je myslím vhodná doba pro opuštění v2. Nicméně vše, co jsme si ukazovali ve všech předchozích dílech, platí i ve verzi 3.