Adam the Automator

author
19 minutes, 12 seconds Read

Ha olyan PowerShell-szkriptet írsz, amelyben nincsenek függvények és nincsenek külső függőségek más szkriptektől, a PowerShell hatókörök fogalma nem sokat számít. A PowerShell globális változók fogalma nem áll előtérben. De ahogy elkezdünk függvényeket, modulokat építeni, és megtanulunk más szkriptekből szkripteket hívni, a téma egyre fontosabbá válik.

Ebben a cikkben mélyreható leckét kapunk arról, hogy mik a hatókörök a PowerShellben, hogyan működnek, és hogyan írhatunk kódot a hatóköröket szem előtt tartva. Mire végzel, megérted a PowerShell globális változóit és még sok mást is!

Tartalomjegyzék

Scopes: Kinda Like Buckets

Valaha írtál már olyan szkriptet, ahol definiálsz egy változót, és amikor ellenőrzöd a változó értékét, az valami más lesz? Lehet, hogy vakargatod a fejed, hogyan változott meg az a változó, amikor egyértelműen definiáltad. Ennek egyik oka lehet, hogy a változó értékét egy másik hatókörben felülírják.

Talán elgondolkodott már azon, hogy bizonyos PowerShell-változóknak miért van értéke, amikor a konzolban hivatkozik rájuk, de a parancsfájlokban nem léteznek. Valószínűleg ezek a változók egy másik “vödörben” vannak, amely éppen nem elérhető.

A hatókörök olyanok, mint a vödrök. A hatókörök befolyásolják, hogy a PowerShell hogyan különíti el a változókat, aliasokat, függvényeket és PSDrive-okat a különböző területek között. A hatókör olyan, mint egy vödör. Ez egy hely, ahol ezeket az elemeket összegyűjthetjük.

A PowerShell indításakor automatikusan létrehozza ezeket a “vödröket” az Ön számára. Ezen a ponton már használjuk a hatóköröket anélkül, hogy észrevennénk. Minden hatóköröket a PowerShell definiál, és az Ön segítsége nélkül jön létre.

Hatókör-típusok

A PowerShell indításakor automatikusan létrehoz négy “vödröt” vagy hatóköröket a különböző elemek elhelyezésére. Önállóan nem hozhat létre hatóköröket. Csak ezekből az alább meghatározott hatókörökből adhat hozzá és távolíthat el elemeket.

Globális hatókör

A PowerShell megnyitásakor meghatározott elemek a globális hatókörben kerülnek beállításra. Ezek az elemek magukban foglalják a rendszer által létrehozott objektumokat, például a PowerShell meghajtókat, valamint mindent, amit egy PowerShell profilban definiált, mivel a profil indításkor fut.

A globális hatókörben lévő elemek mindenhol elérhetők. A globális hatókörben lévő elemekre interaktívan hivatkozhat a konzolon, bármely futtatott szkriptben és bármely függvényben. A PowerShell globális változói mindenhol elérhetők. Emiatt a PowerShell globális változók általános használata a PowerShell globális változók szkriptek közötti használata.

Egyetlen globális hatókör van, amely összességében uralkodik.

Script Scope

A parancsfájl hatókör automatikusan létrejön minden alkalommal, amikor egy PowerShell szkript fut. Több különböző szkript hatókör példánya is lehet. A parancsfájl-tartományok például egy PS1 szkript vagy egy modul futtatásakor jönnek létre.

Kizárólag az adott parancsfájl-tartomány példányban létrehozott elemek hivatkozhatnak egymásra.

Privát tartomány

Tipikusan egy meghatározott elem más tartományokból is elérhető – ez nem igaz a privát tartományban lévő elemekre. A privát hatókörben lévő elemek olyan objektumokat tartalmaznak, amelyek más hatókörök számára rejtve vannak. A privát hatókör a más hatókörökben lévő elemekkel azonos nevű elemek létrehozására szolgál az átfedések elkerülése érdekében.

Helyi hatókör

A többi hatókörrel ellentétben a helyi hatókör egy kicsit más. A helyi hatókör egy mutató a globális, a szkript vagy a privát hatókörre. A helyi hatókör relatív ahhoz a kontextushoz, amelyben a kód éppen fut.

Ha létrehozol egy változót, aliast, függvényt vagy PSDrive-ot anélkül, hogy explicit módon hozzárendelnél neki hatókört (amivel később foglalkozunk), akkor az a helyi hatókörbe kerül.

A hatókörökre való hivatkozás

Most már van fogalma a négyféle létező hatókörről, azt is tudnia kell, hogy kétféleképpen lehet hivatkozni ezekre a hatókörökre.

A PowerShellben kétféleképpen lehet hivatkozni a hatókörökre: névvel vagy számmal. Mindkét módszer ugyanazokra a hatókörökre hivatkozik, csak egyszerűen más módon. Ez a két különböző módja a hatókörökkel való interakciónak.

Nevezett hatókörök

Fentebb a hatókör típusa szakaszban a névvel hivatkozott hatókörökről tanult. A hatókörre való név szerinti hivatkozást intuitív módon nevesített hatókörnek nevezzük. A hatókör név szerinti hivatkozásának fő célja, hogy egy elemet hozzárendeljünk egy hatókörhöz. Az alábbiakban megtanulja, hogyan kell ezt megtenni.

Számozott hatókörök

A név mellett minden hatókörnek van egy nullával kezdődő száma, amely mindig a helyi hatókör lesz. A hatókörök számozása dinamikusan történik az aktuális helyi hatókörhöz képest.

Mihelyt például megnyitunk egy PowerShell munkamenetet, a globális hatókörben dolgozunk. Ekkor a globális hatókör a helyi hatókör (ne feledjük, hogy a helyi hatókör csak egy mutató).

Mivel a helyi hatókör mindig a nulladik hatókör, ekkor a globális hatókör is jelenleg a nulladik hatókör. Amikor azonban ugyanebből a munkamenetből futtatunk egy szkriptet, akkor létrejön egy szkript hatókör. Futtatáskor a helyi hatókör mutatója ekkor már a parancsfájl hatókörére változik. Most a parancsfájl hatókör a nulladik hatókör, a globális hatókör pedig az egyes hatókör.

A hatókörök számozása Ez a folyamat annyi hatókörnél ismétlődik, ahány hatókör van, ahol a helyi hatókör 0. A hatókörök dinamikusan számozódnak a hatókör-hierarchia szerint.

Hatókör-hierarchia és öröklődés

Amint korábban említettük, a PowerShell munkamenet indításakor a PowerShell létrehoz néhány elemet a globális hatókörben. Ezek az elemek lehetnek függvények, változók, aliasok vagy PSDrive-ok. Bármi, amit a PowerShell-munkamenetben definiál, a globális hatókörben is definiálva lesz.

Mivel alapértelmezés szerint a globális hatókörben van, ha olyasmit tesz, ami egy másik hatókör létrehozását eredményezi, például egy szkript végrehajtását vagy egy függvény futtatását, akkor egy gyermek hatókör jön létre, amelynek a szülője a globális hatókör. A hatókörök olyanok, mint a folyamatok, amelyeknek vannak szülei és gyermekei.

Minden, ami a szülő hatókörben – ebben az esetben a globális hatókörben – definiálva van, elérhető lesz a gyermek hatókörben. De ezek az elemek csak abban a hatókörben szerkeszthetők, amelyben definiálták őket.

Tegyük fel, hogy van egy Test.ps1 nevű szkriptünk. Ennek a szkriptnek a belsejében egyetlen sor található az alábbiakban látható módon.

$a = 'Hello world!'

A szkript futtatásakor a $a értéket kap a helyi hatókörben (a szkript futása közben). A Test.ps1 futtatásakor az alábbiakban látható, hogy a szkript végrehajtása után nem tud rá hivatkozni. Mivel a $a értéket a szkript hatókörén belül rendelte hozzá, a globális hatókör (az interaktív konzolon) nem láthatja.

Globális hatókör nem láthatja a változót

Vigyük tovább a példát egy lépéssel, és alakítsuk ki a Test.ps1 szkriptet az alábbi módon. A szkript most megpróbálja kiadni a $a értékét, mielőtt beállítaná azt ugyanabban a hatókörben.

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

A demonstrációhoz rendeljünk értéket a $a-hez az interaktív konzolon. Ez hozzárendeli az értéket a globális hatókörben. Most a szkript fut, a szülő hatókörét (globális) örökli, és látnia kell az értéket.

Az alábbiakban látható, hogy amikor a Test.ps1 végrehajtásra kerül (létrehozva a globális hatókör gyermek hatókörét), láthatja a $a értékét. Azt is láthatjuk, hogy a változó értéke a globális hatókörben is elérhető, mivel ebben a hatókörben lett beállítva. Ez azt jelenti, hogy a $a a szkript (gyermek) és a szülő (globális) hatókörben is elérhető.

Változó elérhető a szkript és a globális hatókörben

El ne feledjük ezt a hatókör-öröklési viselkedést. Ezzel segít a hibaelhárítás során olyan eseteknél, amikor változókonfliktusok lépnek fel, mint például a különböző hatókörökben lévő, azonos nevű változók.

Elemek definiálása és elérése a hatókörökben

Most, hogy már tudja, mi a hatókör és hogyan működnek, hogyan lehet hozzáférni hozzájuk? Lássuk, hogyan lehet a PowerShell segítségével beállítani egy változó hatókörét (és hozzáférni hozzájuk).

Get/Set-Variable

A PowerShellben két cmdlet van, amelyek lehetővé teszik a változók beállítását: Get-Variable és Set-Variable. Ezekkel a cmdletekkel lekérdezheti egy változó értékét vagy meghatározhat egy értéket.

Mindkét cmdlet hasonló egy Name és egy Scope paraméterrel. Ezeknek a paramétereknek a használatával a PowerShell lehetővé teszi, hogy a változó értékét minden hatókörben beállítsa és lekérje.

Helyi hatókörök

A változó helyi hatókörben történő beállításához használja a Set-Variable parancsot, és adja meg a helyi változó nevét és értékét az alábbiakban látható módon.

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

A helyi hatókör mindig alapértelmezett, így a Scope paraméter használatának mellőzése mindig a helyi hatókörben határozza meg a változót.

A lokális hatókörű változó értékének lekérdezéséhez használjuk a Get-Variable paramétert, megadva neki a nevet.

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

Privát/Script/Globális hatókör

Ugyanezeket a paramétereket (Name és Value) használjuk a privát, script és globális változókkal való munka során is. Az egyetlen különbség, hogy ezúttal a Scope paramétert használjuk a hatókör explicit meghatározásához.

A privát, szkript vagy globális hatókörű változók beállításának módszerei ugyanazok. Egyszerűen csak helyettesítsük a Scope paraméterhez átadott értéket Private, Script Global formában.

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

A szkript vagy globális hatókörű változó értékének lekérdezéséhez használjuk a Get-Variable parancsot, megadva a nevet és a hatókörét.

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

Megjegyzés: A Get/Set-Variable cmdletekkel nevek helyett hatókörszámok használatával is hivatkozhat a hatókörökre.

Hatókör “Előfoglalás”

A hatókörökben lévő változókat egy parancsikon segítségével is lekérdezheti és beállíthatja. A PowerShell-cmdletek használata helyett a változókra való hivatkozáskor a hatókör előtagolással jelzi a változót.

Helyi hatókörök

Mivel mindig a helyi hatókör az alapértelmezett, a változó egyszerű definiálása és hivatkozása egy helyi hatókörű változót fog beállítani és lekérdezni

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

Privát/Script/Globális hatókörök

Ha script vagy globális hatóköröket szeretne definiálni és hivatkozni rájuk, akkor a változókat a hatókör nevével és egy pontosvesszővel előzheti meg.

Ha például a $a változót a globális hatókörben szeretné beállítani, akkor a $global: előtaggal előzheti meg az a-t.

$global:a = 'foo'

Ugyanezt megteheti egy script hatókörű változó esetében is.

$script:a = 'foo'

Ha a változókat beállította a preferált hatókörben, akkor ugyanígy hivatkozhat rájuk. Figyeljük meg azt is, hogy a hatókör-előtagot kizárhatjuk, ha a definiált hatókör a helyi hatókör.

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

Hatókörök a scriptblokkokban

A PowerShellnek van egy praktikus konstrukciója, a scriptblokkok. A scriptblockok lehetővé teszik, hogy kódrészleteket mozgassunk és szinte bárhol futtassuk őket.

A PS1 szkriptekhez hasonlóan a scriptblockok is a saját szkript hatókörükben futnak. Amikor egy scriptblokkot hajt végre, lényegében egy PS1 scriptet hajt végre.

Az alábbi példában észrevehető, hogy egy változót a globális hatókörben definiálnak, majd megpróbálják felülírni egy script hatókörben. Ahogy fentebb megtanulta, ez nem fog működni, mert egy gyermek hatókör nem hivatkozhat egy szülő hatókörre.

A gyermek hatókör nem írhatja felül a szülő hatókörét

Ez a példa azt mutatja, hogy amikor a $a változik a scriptblockban, a $a globális változó definíciója nem változik, mert a scriptblock egy script gyermek hatókör.

Dot-sourcing szkriptek (Helyi hatókörök cseréje)

A PowerShell rendelkezik a dot-sourcing nevű koncepcióval. Ez egy olyan módszer, amely lehetővé teszi, hogy egy PS1 szkriptet futtassunk, és helyette mindent, ami a szkript hatókörébe tartozna, a helyi hatókörbe hozzunk.

A PS1 szkriptre való hivatkozás és annak végrehajtása előtt egy pontot (.) teszünk, ezzel “pontforrássá” tesszük a szkript tartalmát, és mindent a helyi hatókörbe hozunk.

A demonstrációhoz ismét van egy Test.ps1 szkriptem, amely az alábbiakban látható módon definiál egy változót.

$a = 'Hello world!'

A PowerShell konzolon állítsunk be egy $a változónak egy értéket, majd a szkriptet az alábbiakban látható módon dot source-ozzuk. Vegyük észre, hogy az eredeti változót felülírta. A PowerShell “összevonta” a két helyi hatóköröket.

Eredeti változó felülírva

Az AllScope tulajdonság használata (opció)

Láttuk, hogyan léphetünk kapcsolatba az egyes hatókörökben lévő elemekkel, de eddig még minden elem egyetlen hatókörben volt definiálva. De mi van akkor, ha nem tudja, hogy egy változó milyen hatókörben van definiálva?

A változó Set-Variable cmdlet segítségével történő definiálásakor a változót egyszerre minden hatókörbe elhelyezheti. Ehhez használja a AllScope értéket a Option paraméterhez.

A Test.ps1 szkriptet úgy módosítottuk, hogy egy változót minden hatókörben beállíthasson. Ez a változó ezután az alábbiakban látható módon kerül kimenetre.

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

Az alábbiakban látható, hogy a globális hatókörben a $a értéket állítja be, és a Test.ps1 szkript végrehajtásra kerül. Azonban ahelyett, hogy nem lenne hatása, a $a értéke felülírásra került. Nemcsak a szkript hatókörében (Write-Output $a) került meghatározásra, hanem a globális hatókörben is felülírásra került.

Változó felülírása a globális hatókörben

A AllScope opció praktikus, de legyünk óvatosak. Ez az opció lényegében megszünteti a hatókörök fogalmát, és mindent összevon.

Funkció hatókörök

A függvény végrehajtásakor a függvényen belüli összes kód a saját gyermek hatókörében van. A függvény hatókörök ugyanazt a gyermek/szülő viselkedést követik, mint a többi hatókör.

Az egyes függvényekhez külön hatókörökkel rendelkezni jó ötlet. Ez lehetővé teszi a jobb ellenőrzést az elemek felett, nem kell aggódni az elemek ütközése miatt, Emellett további előnye a függvényben lévő változók automatikus tisztítása. Amint a függvény befejeződik, a függvényben definiált összes elem törlődik.

A bemutatáshoz másolja be az alábbi függvényt közvetlenül a PowerShell konzolba.

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

A beillesztés után hajtsa végre a függvényt. Vegye észre, hogy a függvényen kívül nem férhet hozzá a $var változóhoz.

PS> Do-ThingPS> $var

Keeping Items Private (Disabling Inheritance)

Tipikusan, ha egy változó a szülői hatókörben van definiálva, akkor az a változó a gyermek hatókörben is definiálva lesz. De lehet, hogy egy változó nevét szeretné használni, de ez a változó neve már definiálva van az egyik munkamenetben futtatandó hatókörben. Ebben az esetben vagy választhat egy másik változónevet, vagy definiálhatja a változót egy privát hatókörben, így az egy privát változó lesz.

A hatókörök használatának egyik módja a konfliktusok csökkentése érdekében a privát hatókör használata. A privát hatókör használata letiltja az öröklést az adott változóra vonatkozóan. Ha több gyermek hatókör jön létre, ezek a gyermek hatókörök nem látják a privát hatókörben definiált változókat.

A Test.ps1 szkript az alábbiakban látható módon adja ki a $a értékét.

Write-Output $a

Az alábbiakban látható, hogy egy privát hatókörű változót definiálok a globális hatókörben, majd végrehajtom a Test.ps1 szkriptet. Általában, ha egy változót a szülői hatókörben definiál, az a változó elérhető lesz a gyermek hatókörben is – nem így van ez egy privát hatókörű változó esetében.

A lenti példában látható, hogy a Test.ps1 parancsfájl végrehajtásával létrehozott szkript gyermek hatókör nem láthatja a szülő hatókörben definiált, privát hatókörű $a változót.

A script hatókör nem láthatja a privát hatókörű változót

A globális hatókörökkel vagy a Set-Variable cmdlet AllScope opciójával ellentétben a privát hatókörű változók kiválóan alkalmasak az elemek felosztására.

Scoping Best Practices

Az a gondolat, hogy a változók globális hatókörben történő definiálása vagy a AllScope opció használata a legjobb megoldás, gyakori. Elvégre minden változó mindenhol elérhető. Nem kell aggódni a hatókörök bonyodalma miatt. Ez ugyan további szabadságot biztosít a definiáltak eléréséhez, de gyorsan kicsúszhat a kezünkből, és nehézzé válhat a hibaelhárítás.

Ahelyett, hogy megpróbálnánk elkerülni a hatókörök használatát, kövessük az alábbi tanácsokat:

  1. Ahelyett, hogy hatóköröket adnánk meg függvényekben, használjunk paramétereket a szükséges információk függvénynek való átadására.
  2. Maradjunk a helyi hatókörön belül, amennyire csak lehetséges.
  3. Ahelyett, hogy globális változókat definiálna egy szkriptből, használja a Write-Output cmdletet, hogy mindent kiadjon, és szükség esetén a konzolról egy változóba mentse.

A lényeg az, hogy fogadjuk el a hatóköröket, és tanuljuk meg előnyösen használni őket ahelyett, hogy megpróbálnánk megkerülni őket.

További olvasnivaló

  • A haladó funkciókról és a funkcióparaméterekről
  • A környezeti változók használata a PowerShellben

Similar Posts

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.