Typy wyliczeniowe w PowerShellu, część 1

Początkowo planowałem wszystko opisać w jednym artykule, ale niestety rozrosło się to znacznie. Więc w pierwszej części skupię się na wykorzystywaniu typów wyliczeniowych w PowerShellu, a tworzenie ich opiszę następnym razem.

Z czym to się je?

Nie jestem programistą, jednak praca z PowerShellem siłą rzeczy wymusza rozumienie choć podstaw platformy .NET. Typy wyliczeniowe są jej częścią i zdecydowanie ułatwiają pracę w PowerShellu. Prosty przykład: czy łatwiej (zwłaszcza na początku) zapamiętać, że aby wyłączyć raportowanie błędów należy użyć wartości dla ErrorAction ‘SilentlyContinue’, czy wolelibyście zawsze używać wartości numerycznej 0? Dziś chcę poświęcić im nieco czasu: gdzie można je znaleźć, jak sprawdzić jaką mają wartość w części pierwszej. W drugiej napiszę jak zdefiniować własne typy wyliczeniowe i czemu moglibyśmy chcieć to zrobić.

Gdzie je znajdziemy?

Typy wyliczeniowe wykorzystujemy w (niemal?) wszystkich komendach (choćby z tego powodu, że parametry *Action wykorzystują typ wyliczeniowy System.Management.Automation.ActionPreference). Aby uzyskać pełną listę najlepiej skorzystać z samego PowerShella. Wykorzystamy do tego Get-Command i kolekcję Parameters, która jest jedną z właściwości obiektów przez tą komendą generowanych. Widać tam typ parametru, a każdy typ posiada właściwość logiczną IsEnum. Kod poniżej:

Get-Command -CommandType cmdlet -Name * |             
    ForEach-Object { $_.Parameters.GetEnumerator() } |             
    Sort-Object -Unique Key |             
    Select-Object -ExpandProperty Value |             
    Where-Object { $_.ParameterType.IsEnum } |             
    Select-Object Name, ParameterType, @{            
        Name = 'CommandName'            
        Expression = {              
            @(Get-Help -Name * -Parameter $_.Name)[0].Name             
        }            
    }            

Na moim komputerze znalazłem 31 takich parametrów. Większość korzysta z unikalnej klasy, więc by z nich skorzystać należałoby poznać możliwe wartości.

A imię jego…

Sposobów na znalezienie wartości ‘opisowych’ jest kilka. Zacznijmy od najprostszej. Wykorzystamy do tego fakt, że informacja o błędzie dotyczącym parametru będącego typem wyliczeniowym jest jednocześnie doskonałym źródłem informacji o tym, jakie wartości prawidłowe:EnumErrorOczywiście bez try/catch to też zadziała, użyłem go tylko po to, by ładnie ‘złamać’ wyświetlaną informację w konsoli. 😉 Istotne części dodatkowo podkolorowałem. A istotne są wartości prawidłowe (których, dzięki takim trikom, nie musimy się uczyć na pamięć), oraz typ używany (który przyda nam się za chwilkę).

Druga opcja to sprawdzić typ wykorzystywany (np. zagłębiając się w rezultat Get-Command) i skorzystać ze statycznych metod typu wyliczeniowego:EnumGetNames Wykorzystałem klasę „matkę” (System.Enum), ale równie dobrze mogłem użyć każdej innej, wszystkie dziedziczą metody statyczne Get*. Metody te pozwalają też uzyskać informację, jaką nazwę przypisano danej wartości numeryczneEnumGetNamePrzeglądając metody statyczne klasy [enum] trudno nie zauważyć metody GetValues. Na logikę spodziewać by się można, że dzięki temu zobaczymy wartości liczbowe. I tak też będzie, mimo że na pierwszy rzut oka wynik metod GetNames i GetValues będzie identyczny.

Tam sięgaj gdzie wzrok nie sięga.

Przyczyną tego, że rezultat GetValues może być na pierwszy rzut oka mało ciekawy jest fakt, że PowerShell domyślnie wykorzystuje metodę ToString() typów wyliczeniowych, a ta zwraca ich nazwę. Skoro nie widać różnicy… to trzeba skorzystać z czegoś, co różnicę uwypukli. Na pierwszy ogień – Get-Member:EnumGetMemberMetody, jak widać, nie są zbyt ciekawe. A jedyna właściwość to value__. Nie trudno odgadnąć, że to tam właśnie jest zapisana wartość numeryczna typu wyliczeniowego. Wiedząc jaka ta wartość jest, możemy użyć jej zamiast nazwy. Pracując z PowerShellem interaktywnie oszczędzimy sobie sporo czasu:

# Uzyjemy:            
ls nonexistent -EA 0            
# Zamiast:            
ls nonexistent -ErrorAction SilentlyContinue                

Przy pomocy prostej funkcji możemy uzyskać pełnię informacji o wartościach parametru komendy, gdy jest on typu wyliczeniowego: nazwę i odpowiadającą jej wartością numeryczną:

function Get-ParameterValues {            
param (            
    [ValidateScript( { Get-Command $_ })]            
    [string]$Command,            
    [string]$Parameter            
)            
            
$CommandInfo = Get-Command $Command            
if ($type = $CommandInfo.Parameters.$Parameter.ParameterType) {            
    if ($type.IsEnum) {            
        [enum]::GetValues($type) | ForEach-Object {            
            New-Object PSObject -Property @{            
                Name = $_.ToString()            
                Value = $_.value__            
            }            
        }            
    }            
}            
}

W skryptach, dla przejrzystości, najlepiej oczywiście używać znaczących i zrozumiałych nazw. W czasie pracy interaktywnej – można skorzystać z wartości numerycznych. Ewentualnie, korzystając z modułu PowerTab, dopełniać wartości takich parameterów przy pomocy [TAB].

~ - autor: Bartek Bielawski w dniu 21 lipca, 2011.

Komentarze 3 to “Typy wyliczeniowe w PowerShellu, część 1”

  1. W programowaniu przyjęło się raczej używać tłumaczenia ‚typ wyliczeniowy’ dla enum, enumeratory z kolei zarezerwowane są dla iteratorów (IEnumerator) 🙂

  2. Dzięki za cenną uwagę. Obięcuję w wolnej chwili poprawić a w drugiej części używać poprawnego nazewnictwa. 🙂

  3. […] W pierwszej części opisałem pracę z typami wyliczeniowymi, które w PowerShellu istnieją out-of-the-box. Drugą część będzie poświęcona temu jak i po co moglibyśmy je tworzyć. Zacznę naturalnie od celu. […]

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

Połączenie z %s

 
%d blogerów lubi to: