Adam the Automator

author
16 minutes, 3 seconds Read

Pokud píšete skript prostředí PowerShell bez funkcí a bez externích závislostí na jiných skriptech, koncept oborů prostředí PowerShell vás příliš nezajímá. Koncept globálních proměnných prostředí PowerShell není v popředí zájmu. Jakmile však začnete vytvářet funkce, moduly a naučíte se volat skripty z jiných skriptů, začne být toto téma důležitější.

V tomto článku dostanete důkladnou lekci o tom, co jsou obory v prostředí PowerShell, jak fungují a jak můžete psát kód s ohledem na obory. Než skončíte, budete rozumět globálním proměnným prostředí PowerShell a ještě mnohem více!

Obsah

Rozsahy: Něco jako kbelíky

Napsali jste někdy skript, ve kterém jste definovali proměnnou, a když jste zjišťovali její hodnotu, bylo to něco jiného? Možná se škrábete na hlavě, jak se tato proměnná změnila, když jste ji jasně definovali. Jedním z důvodů může být přepsání hodnoty proměnné v jiném oboru.

Možná jste se někdy divili, že některé proměnné prostředí PowerShell mají hodnoty, když se na ně odkazujete v konzoli, ale ve vašich skriptech neexistují. Je pravděpodobné, že tyto proměnné jsou v jiném „kbelíku“, který není v danou chvíli k dispozici.

Oblasti jsou jako kbelíky. Obory ovlivňují způsob, jakým PowerShell izoluje proměnné, aliasy, funkce a jednotky PSD mezi různými oblastmi. Obor je jako kbelík. Je to místo, kde se všechny tyto položky shromažďují pohromadě.

Při spuštění prostředí PowerShell pro vás tato „vědra“ automaticky vytvoří. V té chvíli již obory používáte, aniž byste si to uvědomovali. Všechny obory jsou definovány prostředím PowerShell a vytvoří se bez vaší pomoci.

Typy oborů

Když se prostředí PowerShell spustí, automaticky vytvoří čtyři „kbelíky“ neboli obory, do kterých se umístí různé položky. Sami obory vytvářet nemůžete. Můžete pouze přidávat a odebírat položky z těchto níže definovaných rozsahů.

Globální rozsah

Položky definované při otevření prostředí PowerShell jsou nastaveny v globálním rozsahu. Tyto položky zahrnují objekty vytvořené systémem, jako jsou jednotky prostředí PowerShell, a také vše, co jste definovali v profilu prostředí PowerShell, protože váš profil se spouští při spuštění.

Předměty v globálním rozsahu jsou dostupné všude. Na položky v globálním oboru se můžete odkazovat interaktivně na konzole, v libovolném spuštěném skriptu a v libovolné funkci. Globální proměnné prostředí PowerShell jsou k dispozici všude. Z tohoto důvodu je běžné použití globálních proměnných prostředí PowerShell mezi skripty.

Existuje pouze jeden globální obor, který vládne celkově.

Obor skriptu

Obor skriptu se automaticky vytvoří při každém spuštění skriptu prostředí PowerShell. Můžete mít mnoho různých instancí oboru skriptu. Oblasti skriptů se vytvářejí například při spuštění skriptu PS1 nebo modulu.

Na sebe se mohou odkazovat pouze položky vytvořené v dané instanci oblasti skriptů.

Soukromá oblast

Typicky lze k definované položce přistupovat z jiných oblastí – to neplatí pro položky v soukromé oblasti. Položky v soukromém oboru, obsahují objekty, které jsou pro ostatní obory skryté. Soukromý obor se používá k vytváření položek se stejným názvem jako položky v jiných oborech, aby se zabránilo překrývání.

Místní obor

Na rozdíl od ostatních oborů je místní obor trochu jiný. Místní obor je ukazatel na globální, skriptový nebo soukromý obor. Lokální obor je relativní vůči jakémukoli kontextu, ve kterém kód právě běží.

Pokud vytvoříte proměnnou, alias, funkci nebo PSDrive, aniž byste jí explicitně přiřadili obor (o čemž si povíme později), přejde do lokálního oboru.

Odkazování na obory

Teď, když máte představu o čtyřech typech existujících oborů, měli byste také vědět, že existují dva způsoby odkazování na tyto obory.

V prostředí PowerShell existují dva způsoby odkazování na obory – pojmenované nebo číslované. Oba způsoby odkazují na stejné obory, ale jednoduše jiným způsobem. Jedná se o dva různé způsoby interakce s obory.

Pojmenované obory

Ve výše uvedené části Typ oboru jste se dozvěděli o oborech odkazovaných pomocí jména. Odkazování na obor podle jména se intuitivně nazývá pojmenovaný obor. Hlavním účelem odkazování na obor podle jména je přiřazení položky k oboru. Jak to udělat, se dozvíte níže.

Očíslované obory

Kromě jména má každý obor číslo začínající nulou, které bude vždy lokálním oborem. Obory jsou číslovány dynamicky ve vztahu k aktuálnímu místnímu oboru.

Například jakmile otevřete relaci prostředí PowerShell, pracujete v globálním oboru. V tomto okamžiku je globální obor místním oborem (nezapomeňte, že místní obor je pouze ukazatel).

Protože místní obor je vždy obor nula, je v tomto okamžiku globální obor také aktuálně oborem nula. Když však z téže relace spustíte skript, vytvoří se obor skriptu. Při spuštění se pak ukazatel lokálního oboru změnil na obor skriptu. Nyní je obor skriptu obor nula a globální obor je obor jedna.

Obory jsou číslovány Tento proces se opakuje pro tolik oborů, kolik máte oborů, v nichž je lokální obor 0. Obory jsou dynamicky číslovány podle hierarchie oborů.

Hierarchie oborů a dědičnost

Jak již bylo zmíněno, při spuštění relace prostředí PowerShell pro vás prostředí PowerShell vytvoří některé položky v globálním oboru. Tyto položky mohou být funkce, proměnné, aliasy nebo jednotky PSD. Cokoli, co definujete v relaci prostředí PowerShell, bude definováno také v globálním oboru.

Jelikož jste ve výchozím nastavení v globálním oboru, pokud provedete něco, co vytvoří další obor, například spustíte skript nebo funkci, vytvoří se podřízený obor, jehož rodičem je globální obor. Obory jsou jako procesy s rodiči a potomky.

Vše, co je definováno v rodičovském oboru, v tomto případě globálním oboru, bude přístupné v podřízeném oboru. Tyto položky jsou však editovatelné pouze v oboru, ve kterém byly definovány.

Řekněme, že máte skript s názvem Test.ps1. Uvnitř tohoto skriptu je jediný řádek, jak je znázorněno níže.

$a = 'Hello world!'

Při spuštění tohoto skriptu se v lokálním oboru (skript za běhu) přiřadí hodnota $a. Po spuštění skriptu Test.ps1 můžete níže vidět, že po jeho spuštění se na něj nelze odkazovat. Protože $a byla přiřazena během běhu skriptu v oboru skript, globální obor (v interaktivní konzoli) ji nevidí.

Globální obor proměnnou nevidí

Postupme v tomto příkladu o krok dále a vytvořme skript Test.ps1 tak, jak je uvedeno níže. Skript se nyní pokusí vypsat hodnotu $a před jejím nastavením ve stejném oboru.

Write-Output $a$a = 'Hello world!'

Pro demonstraci přiřaďte hodnotu $a v interaktivní konzoli. Tím se přiřadí hodnota v globálním oboru. Nyní se skript spustí, zdědí nadřazený obor (global) a měl by být schopen hodnotu vidět.

Níže vidíte, že když se spustí Test.ps1 (vytvoří podřízený obor globálního oboru), vidí hodnotu $a. Můžete také vidět, že hodnota proměnné je dostupná i v globálním oboru, protože v tomto oboru byla nastavena. To znamená, že $a je dostupná jak v rozsahu skriptu (podřízeném), tak v rodičovském (globálním) rozsahu.

Proměnná je dostupná v rozsahu skriptu i globálním rozsahu

Pamatujte si toto chování dědičnosti rozsahu. Tím vám pomůže při řešení problémů, kdy se vyskytnou konflikty proměnných, například proměnné v různých oborech se stejným názvem.

Definice a přístup k položkám v oborech

Když už víte, co je to obor a jak fungují, jak k nim přistupovat? Podívejme se, jak pomocí prostředí PowerShell nastavit obor proměnné (a jak k nim přistupovat).

Get/Set-Variable

V prostředí PowerShell existují dvě rutiny, které umožňují nastavovat proměnné a nazývají se Get-Variable a Set-Variable. Tyto rutiny umožňují získat hodnotu proměnné nebo definovat její hodnotu.

Obě rutiny mají podobný parametr Name a Scope. Pomocí těchto parametrů umožňuje prostředí PowerShell nastavovat a načítat hodnoty proměnných ve všech oborech.

Místní obory

Chcete-li nastavit proměnnou v místním oboru, použijte příkaz Set-Variable a zadejte mu název místní proměnné a hodnotu, jak je uvedeno níže.

PS> Set-Variable -Name a -Value 'foo'

Místní obor je vždy výchozí, takže nepoužitím parametru Scope bude proměnná vždy definována v místním oboru.

Chcete-li získat hodnotu proměnné s lokálním rozsahem, použijte parametr Get-Variable a poskytněte mu její název.

PS> Get-Variable -Name aName Value---- -----a foo

Soukromé/skriptové/globální rozsahy

Stejné parametry (Name a Value) použijete i při práci se soukromými, skriptovými a globálními proměnnými. Jediný rozdíl je v tom, že tentokrát použijete parametr Scope k explicitnímu definování oboru.

Metody pro nastavení soukromé, skriptové nebo globálně oborové proměnné jsou stejné. Stačí nahradit hodnotu předanou parametru Scope jako Private, Script Global.

PS> Set-Variable -Name a -Value 'foo' -Scope <Private|Script|Global>

Chcete-li získat hodnotu skriptové nebo globálně omezené proměnné, použijte Get-Variable a zadejte její název a rozsah.

PS> Get-Variable -Name a -Scope <Script|Global>Name Value---- -----a foo

Poznámka: Pomocí rutin Get/Set-Variable můžete také odkazovat na obory pomocí čísel oborů namísto názvů.

Obor „Prefacing“

Proměnné v oborech můžete načítat a nastavovat také pomocí zkratky. Namísto použití rutin prostředí PowerShell budete při odkazování na proměnnou předřazovat obor.

Místní obory

Protože je místní obor vždy výchozí, pouhým definováním proměnné a odkazem na ni nastavíte a načtete proměnnou v místním oboru

PS> $a = 'foo'PS> $afoo

Soukromé/skriptové/globální obory

Pokud chcete definovat a odkazovat na skriptové nebo globální obory, můžete proměnným předřadit název oboru a středník.

Chcete-li například nastavit proměnnou $a v globálním oboru, můžete ji uvozovat $global:.

$global:a = 'foo'

To samé lze udělat pro proměnnou s oborem skriptu.

$script:a = 'foo'

Jakmile jsou proměnné nastaveny v preferovaném oboru, odkazujete na ně stejným způsobem. Všimněte si také, že předvolbu oboru můžete vyloučit, pokud je definovaným oborem lokální obor.

PS> $global:a = 'foo'PS> $global:afooPS> $afoo

Obory v blocích skriptů

PowerShell má praktickou konstrukci zvanou bloky skriptů. Scriptblocky umožňují přesouvat kousky kódu a spouštět je prakticky kdekoli.

Stejně jako skript PS1 se scriptblocky spouštějí ve vlastním oboru skriptu. Když spustíte skriptblok, spustíte v podstatě skript PS1.

Všimněte si v následujícím příkladu, kde je proměnná definována v globálním oboru a pak se ji pokusíte přepsat v oboru skriptu. Jak jste se dozvěděli výše, nebude to fungovat, protože podřízený obor se nemůže odkazovat na nadřízený obor.

Podřízený obor nemůže přepsat nadřízený obor

Tento příklad ukazuje, že když se v bloku skriptů změní $a, definice globální proměnné pro $a se nezmění, protože blok skriptů je podřízeným oborem skriptu.

Dot Sourcing Scripts (Swapping Local Scopes)

PowerShell má koncept zvaný dot-sourcing. Jedná se o metodu, která umožňuje spustit skript PS1 a místo toho přenést do místního oboru vše, co by patřilo do skriptového oboru.

Vložením tečky (.) před odkaz na skript PS1 a jeho spuštěním se obsah skriptu „dot source“ přenese do místního oboru.

Pro demonstraci mám opět skript Test.ps1, který definuje proměnnou, jak je uvedeno níže.

$a = 'Hello world!'

V konzole prostředí PowerShell nastavte hodnotu proměnné $a a poté tento skript „dot source“, jak je uvedeno níže. Všimněte si, že původní proměnná byla přepsána. Prostředí PowerShell „sloučilo“ oba místní obory dohromady.

Původní proměnná přepsána

Použití vlastnosti AllScope (možnost)

Viděli jste, jak pracovat s položkami v konkrétních oborech, ale zatím je každá položka stále definována v jednom oboru. Co když ale nevíte, v jakém oboru je proměnná definována?“

Při definování proměnné pomocí rutiny Set-Variable můžete proměnnou umístit do všech oborů najednou. K tomu použijte hodnotu AllScope pro parametr Option.

Pro demonstraci byl skript Test.ps1 upraven tak, aby nastavil proměnnou ve všech oborech. Tato proměnná je pak vypsána, jak je znázorněno níže.

Set-Variable -Name a -Value 'Hello world!' -Option AllScopeWrite-Output $a

Níže pak vidíte, že v globálním oboru je nastavena hodnota $a a skript Test.ps1 je spuštěn. Avšak místo toho, aby to nemělo žádný účinek, byla přepsána hodnota $a. Nejenže byla definována v oboru skriptu (Write-Output $a), ale byla přepsána i v globálním oboru.

Proměnná přepsána v globálním oboru

Volba AllScope je šikovná, ale buďte opatrní. Tato volba v podstatě ruší koncept oborů a slučuje vše dohromady.

Obory funkcí

Při spuštění funkce je veškerý kód v rámci této funkce ve svém vlastním podřízeném oboru. Oblasti funkcí se chovají stejně jako ostatní oblasti podřízené/rodičovské.

Mít pro každou funkci samostatné oblasti je dobrý nápad. Umožňuje lepší kontrolu nad položkami, které se nemusí starat o konflikt položek, Poskytuje také další výhodu automatizovaného čištění proměnných ve funkci. Jakmile funkce skončí, všechny položky definované ve funkci budou vymazány.

Pro demonstraci zkopírujte/vložte níže uvedenou funkci přímo do konzoly prostředí PowerShell.

Function Do-Thing { $var = 'bar'}

Po vložení funkci spusťte. Všimněte si, že k proměnné $var nemáte přístup mimo funkci.

PS> Do-ThingPS> $var

Udržování položek v soukromí (vypnutí dědičnosti)

Obvykle platí, že pokud je proměnná definována v rodičovském oboru, bude tato proměnná definována i v podřízeném oboru. Ale možná byste chtěli použít název proměnné, ale tento název proměnné již byl definován v jednom z rozsahů, který má být spuštěn v relaci. V takovém případě můžete buď zvolit jiné jméno proměnné, nebo definovat proměnnou v soukromém oboru, čímž se stane soukromou proměnnou.

Způsob, jak použít obory pro omezení konfliktů, je použití soukromého oboru. Použití privátního oboru zakáže dědičnost této konkrétní proměnné. Pokud je vytvořeno více podřízených oborů, tyto podřízené obory neuvidí žádné proměnné definované v soukromém oboru.

Skript Test.ps1 vypíše hodnotu $a, jak je znázorněno níže.

Write-Output $a

Na obrázku níže vidíte, že definuji proměnnou se soukromým oborem v globálním oboru a poté spustím skript Test.ps1. Obvykle platí, že když definujete proměnnou v nadřazeném oboru, bude tato proměnná dostupná i v podřízeném oboru – ne tak v případě privately-scoped proměnné.

V níže uvedeném příkladu je vidět, že podřízený obor skriptu vytvořený spuštěním skriptu Test.ps1 neviděl proměnnou $a definovanou v nadřazeném oboru s privátním přístupem.

Obsah skriptu nevidí proměnnou s privátním rozsahem

Na rozdíl od globálních rozsahů nebo možnosti AllScope rutiny Set-Variable jsou proměnné s privátním rozsahem vynikajícím způsobem rozdělení položek.

Osvědčené postupy pro určování rozsahu

Myslet si, že definování proměnných v globálním rozsahu nebo použití možnosti AllScope je správná cesta, je běžné. Všechny proměnné jsou přece dostupné všude. Není třeba se zabývat komplikacemi s rozsahy. To sice poskytuje další volnost přístupu k tomu, co je definováno, ale může se to rychle vymknout kontrole a ztížit řešení problémů.

Místo toho, abyste se snažili zabránit používání oborů, postupujte podle těchto rad:

  1. Místo zadávání oborů ve funkcích používejte parametry pro předání požadovaných informací funkci.
  2. Držte se co nejvíce v lokálním oboru.
  3. Místo definování globálních proměnných ze skriptu použijte rutinu Write-Output, která vše vypíše a v případě potřeby uloží do proměnné z konzoly.

Hlavním bodem je přijmout obory a naučit se je využívat ve svůj prospěch, místo abyste se je snažili obcházet.

Další čtení

  • O pokročilých funkcích a parametrech funkcí
  • Používání proměnných prostředí v prostředí PowerShell

.

Similar Posts

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.