IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

13. diel - PowerShell - Pokročilé funkcie (parameter sety, záver)

V minulej lekcii, PowerShell - Pokročilé funkcie (výkonný kód) , sme sa zoznámili s pokročilými funkciami PowerShellu a výkonným kódom

V dnešnej lekcii kurze PowerShell frameworku uzavrieme sekciu s pokročilými funkciami PowerShellu. Vysvetlíme si, čo je parameter set a ako ho využiť a taktiež si pripravíme podporu pre online pomoc pre našej funkciu.

Parameter set

Niekedy v našom kóde, kde máme viac parametrov, potrebujeme zaručiť, aby funkcia či skript akceptovala jeden alebo druhý parameter, ale nie obaja zároveň. Toto môžeme zabezpečiť podmienkami, kde na začiatku výkonného kódu definujeme, ktorý parameter je braný ako hlavný. V prípade, že sú použité oba, vykonáme override na vopred definovaný parameter.

Toto nie je však ideálne riešenie, pretože nám týmto narastie zbytočne množstvo výkonného kódu, čo je vždy nežiaduce. K tomuto v PowerShellu slúži tzv. ParameterSet, čo môžeme chápať ako skupinu, do ktorej jednotlivé parametre patrí. Ak použijeme parameter z jednej skupiny, parameter z druhej skupiny je nedostupný. Taktiež jeden parameter môže patriť do viacerých skupín, či parameter setov.

Ako príklad si uvedieme príkaz Get-Process, kde môžeme získať informácie o bežiacom procese buď pomocou PID (Process ID) alebo mená procesu:

Dotaz pomocou mena procesu

Windows PowerShell
PS C:\Dev> Get-Process -Name notepad++

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    288      21    11684      23028       0,61   7816   1 notepad++

Program notepad ++ však musí bežať, inak nebude proces nájdený.

Pomocou PID

Windows PowerShell
PS C:\Dev> Get-Process -Id 19684

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    289      20    11364      22912       0,64   7816   1 notepad++

PID procesu môžeme zistiť v Task Managera (Správca úloh).

V oboch prípadoch dostaneme rovnaký výsledok, avšak dotaz na bežiaci process bol zadaný použitím rôznych vstupných parametrov. Ak sa pokúsime použiť oba parametre zároveň, PowerShell nám vypíše chybu, ktoré sama o sebe nič moc nehovorí, ale znamená, že každý z parametrov je v inom parameter sete a príkaz nedokáže použiť obidva zároveň.

Teda je na užívateľovi, aby zvolil jeden alebo druhý parameter, ale né obaja zároveň:

Windows PowerShell
PS C:\Dev> Get-Process -Name notepad++ -Id 19684
Get-Process : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:1
+ Get-Process -Name notepad++ -Id 19684
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Process], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.GetProcessCommand

Príprava funkcie pre parameter set

Pre demonštráciu si pripravíme jednoduchú funkciu, ktorá nám zobrazí čas v dvoch rôznych formátoch, avšak vždy môže byť použitý len jeden formát. Na zaručenie toho, že iba jeden formát bude použitý, použijeme parameter set. K tomu, aby sme definovali parameter set, použijeme u daného parametra atribút ParameterSetName a priradíme meno danej skupiny, ktorá je dátového typu reťazec:

function Get-CustomDate {
    [CmdletBinding()]
    param (
        [switch][parameter(ParameterSetName='short')]$ShortFormat,
        [switch][parameter(ParameterSetName='long')]$LongFormat
    )

    switch ($PSCmdlet.ParameterSetName){
        'short' {
            Get-Date -Format 'yyyy-dd-MM'
        }
        'long' {
            Get-Date -UFormat '%c'
        }
    }
}

Teraz otestujeme, či parameter set funguje:

Windows PowerShell
PS C:\Dev> Get-CustomDate -ShortFormat

2020-24-11

Celé dátum:

Windows PowerShell
PS C:\Dev> Get-CustomDate -LongFormat

Tue Nov 24 06:00:51 2020

Obaja parametre zároveň:

Windows PowerShell
PS C:\Dev> Get-CustomDate -LongFormat -ShortFormat

Get-CustomDate : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:1
+ Get-CustomDate -LongFormat -ShortFormat
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-CustomDate], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : AmbiguousParameterSet,Get-CustomDate

Ako vidno na poslednom príklade, parameter set funguje ako má. Užívateľ, ktorý použije túto našu funkciu je nútený použiť buď jeden alebo druhý parameter, né však obaja zároveň. Taktiež výkonný kód má iba 7 riadkov, čo by v prípade, že by sme nepoužili parameter set, bolo oveľa viac.

DefaultParame­terSetName

Ak máme funkciu či skript, ktorá má viac parametrov, a chceme, aby tento parameter bolo možné použiť ako s jednou alebo druhou skupinou, je možné ho priradiť do defaultný skupiny, ktorá je definovaná pomocou tagu DefaultParameterSetName. Pokiaľ tento tag použijeme, automaticky všetky parametre, ktoré nemajú pridelený žiadny iný set, spadajú do tohto defaultu.

Pre demonštráciu použijeme našu predchádzajúcu funkciu, ktorú rozšírime o jeden ďalší parameter, ktorý spadá do defaultného parameter setu. Je teda možné ho použiť pri oboch predchádzajúcich parametrov, avšak tieto dva predchádzajúce parametre opäť nie je možné použiť zároveň:

function Get-CustomDate {
    [CmdletBinding(DefaultParameterSetName='default')]
    param (
        [switch][parameter(ParameterSetName='short')]$ShortFormat,
        [switch][parameter(ParameterSetName='long')]$LongFormat,
        [switch]$ShowAsPopup
    )

    switch ($PSCmdlet.ParameterSetName){
        'short' {
            $Date = Get-Date -Format 'yyyy-dd-MM'
        }
        'long' {
            $Date = Get-Date -UFormat '%c'
        }
    }
    switch ($ShowAsPopup){
        $true {
            Add-Type -AssemblyName PresentationFramework
            [System.Windows.MessageBox]::Show($Date,$($PSBoundParameters.Keys | Where-Object {$_ -match 'format'}))
        }
        default {
            $Date
        }
    }
}

K zobrazenie popup okna využijeme triedu System.Windows.MessageBox.

Po reštartovaní konzole môžeme využiť ďalšie parameter pre popup:

Get-CustomDate -short -ShowAsPopup

výsledok:

PowerShell

Priradenie parametra do viacerých skupín

Ako už bolo spomenuté vyššie, ParameterSety je možno prelínať medzi sebou. Možno teda dosiahnuť to, že dané parametre je možné medzi sebou rôzne využívať.

Na príklade si ukážeme, ako parameter priradiť do dvoch rôznych skupín, avšak nie do defaultný skupiny. Opäť využijeme predchádzajúcu funkciu:

function Get-CustomDate {
    [CmdletBinding(DefaultParameterSetName='default')]
    param (
        [switch][parameter(ParameterSetName='short')]$ShortFormat,
        [switch][parameter(ParameterSetName='long')]$LongFormat,
        [parameter(ParameterSetName='short')]
        [parameter(ParameterSetName='long')]
        [switch]$ShowAsPopup,
        [parameter(ParameterSetName='long')]
        [switch]$ShowComputerName
    )

    switch ($ShowComputerName){
        $true {$ComputerName = " (computer name $env:COMPUTERNAME)"}
        default {$ComputerName = $null}
    }

    switch ($PSCmdlet.ParameterSetName){
        'short' {
            $Date = Get-Date -Format 'yyyy-dd-MM'
        }
        'long' {
            $Date = Get-Date -UFormat '%c'
        }
    }
    switch ($ShowAsPopup){
        $true {
            Add-Type -AssemblyName PresentationFramework
            [void][System.Windows.MessageBox]::Show("${Date}${ComputerName}",$($PSBoundParameters.Keys | Where-Object {$_ -match 'format'}))
        }
        default {
            "${Date}${ComputerName}"
        }
    }
}

Pre demonštráciu som pridal parameter -ShowComputerName, ktorý je ale možné využiť len v kombinácii s parametrom -LongFormat, nie však s parametrom -ShortFormat, ale zároveň môže byť použitý v kombinácii aj bez parametra -ShowAsPopup. Tiež si všimnite, že ak použijem akýkoľvek parameter z daného setu, tento set automaticky použije dané parametre typu switch:

Windows PowerShell
Get-CustomDate -ShowComputerName

Fri Jan 15 07:11:00 2021 (computer name WL046418)

Podpora online pomocníka

Ako už bolo povedané v predošlých lekciách, každá zložitejšie funkcie by mala mať svoju comment based nápovedu. Táto nápoveda sa potom zobrazí pomocou príkazu Get-Help.

Pri preskúmaní tohto príkazu zistíme, že ponúka parameter typu switch -Online. Pokiaľ tento parameter použijeme na funkciu, ktorá nie je na online nápovedu pripravená, PowerShell nám zobrazí túto chybu:

Windows PowerShell
Get-Help Get-CustomDate -Online

Get-Help : The online version of this Help topic cannot be displayed because the Internet address (URI) of the Help topic is not specified in the command code or in the help file for the command.
At line:1 char:1
+ Get-Help Get-CustomDate -Online
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-Help], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.GetHelpCommand

Funkciu je teda na online pomoc pripraviť a táto príprava je veľmi jednoduchá, avšak je potrebné splniť tieto požiadavky:

  • adresa, na ktorú nápoveda odkazuje, musí existovať. Ak sa teda jedna o interný modul alebo funkcie, je dobré mať túto nápovedu buď na svojom internom web serveri alebo na verejnom serveri, napr. Github a iné.

K príprave pre online nápovedu postačí modifikovať funkciu pridaním tagu HelpUri a špecifikovaním adresy vo formáte HTTP alebo HTTPS:

function Get-CustomDate {
    [CmdletBinding(
        DefaultParameterSetName='default',
        HelpUri='http://google.com'
    )]
    param (
        [switch][parameter(ParameterSetName='short')]$ShortFormat,
        [switch][parameter(ParameterSetName='long')]$LongFormat,
        [parameter(ParameterSetName='short')]
        [parameter(ParameterSetName='long')]
        [switch]$ShowAsPopup,
        [parameter(ParameterSetName='long')]
        [switch]$ShowComputerName
    )

    switch ($ShowComputerName){
        $true {$ComputerName = " (computer name $env:COMPUTERNAME)"}
        default {$ComputerName = $null}
    }

    switch ($PSCmdlet.ParameterSetName){
        'short' {
            $Date = Get-Date -Format 'yyyy-dd-MM'
        }
        'long' {
            $Date = Get-Date -UFormat '%c'
        }
    }
    switch ($ShowAsPopup){
        $true {
            Add-Type -AssemblyName PresentationFramework
            [void][System.Windows.MessageBox]::Show("${Date}${ComputerName}",$($PSBoundParameters.Keys | Where-Object {$_ -match 'format'}))
        }
        default {
            "${Date}${ComputerName}"
        }
    }
}

Teraz keď zavoláme príkaz nápovedy:

Get-Help Get-CustomDate -Online

PowerShell nás presmeruje na túto stránku, v našom prípade je použitá na ukážku funkcionality stránka Google.com.

Záverom

Aj keď to môže znieť vtipne, nutné dodať, že ak plánujeme zložitejšie kombinácie parameter setov v našej funkcii, je dobré si toto rozkresliť na papier formou množín, ktoré sa budú prelínať. Každopádne parameter set je skvelý nástroj, ako dokonale pripraviť vstupy do našej funkcie a ďalej zredukovať množstvo výkonného kódu. Čo sa týka online pomocníka, toto už je naozaj čerešnička na torte, ale jedná sa o ďalší krok k zlepšeniu kvality kódu a podpory pre užívateľov našej funkcie či modulu.

V ďalšej lekcii, PowerShell - Pester testy , si vysvetlíme, čo je to Pester a ako písať testy pre PowerShell kód.


 

Predchádzajúci článok
PowerShell - Pokročilé funkcie (výkonný kód)
Všetky články v sekcii
PowerShell
Preskočiť článok
(neodporúčame)
PowerShell - Pester testy
Článok pre vás napísal Vojtěch Kašný
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Aktivity