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.
DefaultParameterSetName
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:
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.