PowerShell – efektywniej, część 7.

Minął prawie miesiąc od ostatniego wpisu… dla mnie był to miesiąc wyjątkowo długi. Kończymy powoli wdrażanie Windows 7 w naszej firmie, a wiadomo jak to jest – końcówki zwykle są najgorsze, szczególnie gdy innych spraw również nie można odłożyć na później. Skutek jest taki jak widać – blog musiał nieco poczekać… Dziś zamknąć zamierzam kwestie związane z zaawansowanymi funkcjami/ skryptami. Nasza zaawansowana (choć niezbyt funkcjonalna) ma już niemal wszystko. Brakuje tylko jednego – pomocy. W przypadku cmdletów pomoc jest tworzona przy pomocy plików maml. Pisanie ich na piechotę nie należy do wdzięcznych czynności, można to sobie znacznie uprościć korzystając z narzędzia Cmdlet Help Editor. Pisząc zaawansowane funkcje mamy zadanie znacznie uproszczone. W zasadzie całość sprowadza się do umieszczenia odpowiednio sformatowanego komentarza w odpowiednim miejscu. Zasady przypominają nieco regulamin dotyczący spalonego w piłce nożnej: niby wszystko jest proste, ale jak się zacznie wyjaśniać komuś, robi się coraz mniej “prosto”. Puszczam oczko W zasadzie budowanie pomocy sprowadza się do dodania komentarza w formacie:

<#
.Nagłówek
    Treść
.Dwuczłonowy Nagłówek
    Treść
#>

Dokładny opis wszystkich elementów znajduje się w pomocy (about_comment_based_help), ja wspomnę o najistotniejszych (moim zdaniem):

  1. Synopsis – krótki opis naszej funkcji
  2. Description – opis obszerniejszy, bardziej szczegółowy
  3. Example – przykłady, każdy przykład umieszczamy w osobnej sekcji Example a sekcji takich możemy definiować ile chcemy (nawet jeśli istnieje jakiś limit, to trudno będzie do niego “dobić”
  4. Notes – dodatkowe informacje, które nie pojawią się w widoku domyślnym
  5. Parameter MojParametr – opis konkretnego parametru

Ale to dopiero początek, dalej zaczyna się cała litania innych warunków, po kolei więc:

  • można użyć zarówno komentarzy blokowych (<# #>), “tradycyjnych” (# jako pierwszy znak w linii) oraz mieszanki obu
  • komentarz do funkcji można umieścić “w ciele”, lub tuż nad słowem kluczowym “function”
  • umieszczając pomoc nad funkcją, możemy zostawić maksymalnie jedną linię pustą pomiędzy końcem komentarza a początkiem funkcji.
  • umieszczając pomoc w ciele funkcji, musimy pamiętać by umieścić go przed blokiem param () i [CmdletBinding()]
  • w przypadku pomocy do skryptu – musimy umieścić komentarz na jego początku lub końcu
  • jeśli chcemy dodać linie #requires na początku skryptu – musimy odseparować ją pustą linią od bloku zawierającego pomoc
  • umieszczenie pomocy na końcu skryptu i podpis elektroniczny wzajemnie się wykluczają (niedopatrzenie Puszczam oczko ) – podpis jest komentarzem, więc automatycznie blok pomocy nie jest ostatni i przestaje być obsługiwany
  • jeśli chcemy pomoc skryptu umieścić na jego początku musimy zadbać o to, by pomoc nie “przykleiła” nam się do pierwszej funkcji znajdującej się w skrypcie
  • jakakolwiek literówka w nagłówkach pomocy (n.p.: .Synosis) automatycznie sprawi, że pomoc się nie pojawi w ogóle
  • każdy nagłówek musi być w osobnej linii, sekcja musi zaczynać się w linii następnej i kończyć w linii poprzedzającej następny nagłówek
  • komentarz musi stanowić jedną całość – jeśli będą przerwy między częściami, brana pod uwagę będzie tylko ta część, której położenie zgadza się z zasadami wymienionymi powyżej
  • opis parametrów można umieszczać zarówno tuż nad nimi, jak i w treści “głównej” pomocy

Jak widać – miejsc na potencjalne pomyłki nie brakuje. Próbowałem sobie wyłapywanie błędów (szczególnie literówek) ułatwić jakiś czas temu (dokładnie w czasie Scripting Games 2010) – wtedy też napisałem prostą funkcję, która miała mi w wyłapywanie błędów pomóc. Bazuje ona na wyrażeniach regularnych i pewnie wymagałaby poprawek – pisałem ją w czasach gdy o tych ostatnich wiedziałem zdecydowanie mniej niż teraz. Ale na pewno może się ona przydać od czasu do czasu, by wyłapać najbardziej bagatelne błędy…

Tyle zasady. A jak najlepiej budować taką pomoc? Synopsis i Description to moim zdaniem absolutne minimum. Dobrze jest też umieścić choć kilka przykładów użycia naszej funkcji. Odnośnie parametrów – preferuję umieszczania pomocy do nich bezpośrednio na nimi, w bloku param. Dzięki temu, moim zdaniem, łatwo tę pomoc “wyłapać” w czasie modyfikowania skryptu/ funkcji. A i dodając nowy parametr możemy od razu wzbogacić go o odpowiednią pomoc. Wyjątkiem będą tu parametry dodawane w zaawansowanych funkcjach automatycznie, jak WhatIf, Confirm, Debug i Verbose.

Pozostałe elementy pomocy używam niezmiernie rzadko. Możliwości jest sporo, więc najlepiej korzystać z nich z głową, by nie przesadzić… Jak pomoc będzie zbyt przeładowana – nikomu nie będzie się chciało jej czytać. Puszczam oczko

Na koniec nasza funkcja, tym razem już odpowiednio uzbrojona w system pomocy:

function Get-Foo {            
            
<#

.Synopsis
    Wyświetla literki i cyferki.

.Description
    Funkcja wyświetla literki i cyferki, w zależnosci od potrzeb.
    Liczby są formatowane jako waluta (C4), procenty (P4) 
    i zwykłe liczby (N4).
    W przypadku słów nie jest używane żadne specjalne formatowanie.

.Example
    Get-Foo Slowo
    Slowo to moje slowo

    Wyświetla wybrany string.

.Example
    Get-Foo -Liczba .24 -Format P4
    Moja liczba: 24.0000 %

    Wyświetla liczbę sformatowaną w wybrany sposób.

.Parameter WhatIf
    Dodawany automatycznie.
    Pomoc do niego możemy umieścić jedynie w taki sposób.

.Parameter Confirm
    I tu podobnie...
#>            
            
[CmdletBinding(            
    SupportsShouldProcess = $true,            
    ConfirmImpact = 'Medium',            
    DefaultParameterSetName = 'Domyslny'            
)]            
param (            
    # Liczba, którą chcemy wyświetlić.            
    [Parameter(            
        Mandatory = $true,            
        HelpMessage = 'Pomocy!',            
        ValueFromPipeline = $true,            
        Position = 0,            
        ParameterSetName = 'Liczby'            
    )]            
    [double]$Liczba,            
            
    # Pojedyncze słowo, które chcemy wyświetlić.            
    [Parameter(            
        Mandatory = $true,            
        HelpMessage = 'Pomocy!',            
        ValueFromPipelineByPropertyName = $true,            
        Position = 0,            
        ParameterSetName = 'Domyslny'            
    )]            
    [ValidatePattern('^\w+$')]            
    [string]$Slowo,            
            
    # Format, który zostanie użyty do wyświetlenia podanej liczby.            
    [Parameter(            
        Position = 1,            
        ParameterSetName = 'Liczby',            
        Mandatory = $true,            
        HelpMessage = 'Pomozcie mi!'            
    )]            
    [ValidateSet('P4','N4','C4')]            
    [string]$Format            
            
)            
            
begin {            
    Write-Verbose "Format: $Format"            
    Write-Verbose "Liczba: $Liczba"            
    Write-Verbose "Slowo: $Slowo"            
    if ($Format) {            
        Write-Debug "Wygląda na to, że używamy liczby."            
    }            
}            
            
process {            
    if ($psCmdlet.ShouldProcess(            
        "Cel: $Slowo $Liczba",            
        "Operacja: Wyświetl"            
    )) {            
            
        switch ($psCmdlet.ParameterSetName) {            
            Domyslny {             
                "{0} to moje slowo" -f $Slowo            
            }            
            Liczby {             
                "Moja liczba: {0:$Format}" -f $Liczba             
            }            
        }            
    }            
}            
}

W następnej części zamierzam zająć się modułami. Ponieważ temat ten jest dość obszerny, nie wykluczone że rozbiję go na kilka wpisów. Byleby tylko czasu i zapału na pisanie nie zabrakło… Puszczam oczko

~ - autor: Bartek Bielawski w dniu Listopad 29, 2011.

Skomentuj

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

Logo WordPress.com

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

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

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

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

 
%d blogerów lubi to: