Hur omfattningar påverkar PowerShell-skript
I batchskript har förändringar i miljövariabler som standard en global inverkan på den aktuella sessionen. För PowerShell är det exakta motsatsen sant eftersom omfattningar används för att isolera ett scripts modifikationer. Här undersöker vi hur omfattningar påverkar PowerShell-skript och hur man arbetar i och runt dem.
Vad är ett räckvidd?
I PowerShell refererar en "scope" till den nuvarande miljön där ett skript eller kommandoskal fungerar. Områden används för att skydda vissa föremål inom miljön från oavsiktligt modifierad av skript eller funktioner. Särskilt är följande saker skyddade mot modifiering av kommandon som körs från ett annat omfång, om inte annat anges av parametrar i dessa kommandon:
- variabler
- alias
- funktioner
- PowerShell-enheter (PSDrives)
Nya områden skapas när du kör ett skript eller en funktion, eller när du skapar en ny session eller ett exempel på PowerShell. Områden som skapas genom att köra skript och funktioner har ett "föräldra / barn" -förhållande med omfattningen från vilken de skapades. Det finns några områden som har särskilt speciella betydelser och kan nås med namn:
- De Global räckvidd är det räckvidd som skapas när PowerShell startar. Den innehåller variabler, alias, funktioner och PSDrives som är inbyggda i PowerShell, liksom alla som tillverkas av din PowerShell-profil.
- De Lokal omfattning avser vad som nuvarande omfattning är. När du startar PowerShell kommer det att referera till det globala räckviddet, inom ett skript kommer det att vara Script-omfattningen, etc..
- De Manus Räckvidd skapas när ett skript körs. De enda kommandon som fungerar inom detta räckvidd är de som finns i manuset.
- Privat Områden kan definieras inom det nuvarande omfånget för att förhindra att kommandon i andra områden kan läsa eller ändra saker som de annars skulle ha tillgång till.
Områden kan också hänvisas till med nummer i vissa kommandon, där nuvarande räckvidd betecknas noll och dess förfäder hänvisas till genom att öka heltal. Till exempel, inom ett skript som körs från det globala räckviddet, skulle Script-räckvidden vara 0 och det globala räckviddet skulle vara 1. En räckvidd som var nästare inuti Script-räckvidden, såsom en funktion, skulle referera till det globala räckviddet som 2 Negativa siffror kommer dock inte att fungera för att referera till barnomfattningar. Årsaken till detta kommer snart att uppstå.
Hur omfattningar påverkar kommandon
Som tidigare nämnts kommer kommandon som exekveras inom ett räckvidd inte att påverka saker i ett annat räckvidd om inte specifikt berättas att göra det. Om exempelvis $ MyVar existerar i det globala räckviddet och ett skript kör ett kommando för att ställa in $ MyVar till ett annat värde, förblir den globala versionen av $ MyVar oförändrad medan en kopia av $ MyVar placeras i Script-räckvidden med den nya värde. Om en $ MyVar inte finns kommer ett skript att skapa det inom Script-räckvidd som standard - inte i det globala räckviddet. Detta är viktigt att komma ihåg när du lär dig om det faktiska föräldraskapet mellan barn och barn.
Föräldrars / barns förhållande mellan scopes i PowerShell är envägs. Kommandon kan se in och, eventuellt ändra, det nuvarande omfånget, dess förälder och eventuella omfång ovanför. De kan emellertid inte se eller ändra saker i några barn av nuvarande omfattning. Det här beror framförallt på att, när du väl har flyttat till ett föräldraomfattning, har barnets räckvidd redan förstörts eftersom det har uppfyllt sitt syfte. Till exempel, varför skulle du behöva se eller ändra en variabel i Script-räckvidden, från det globala räckviddet, efter att manuset avslutats? Det finns många fall där du behöver ett skript eller funktionens ändringar för att kvarstå efter det att det har fullföljts, men inte så många där du skulle behöva göra ändringar i objekt inom skriptets eller funktionens räckvidd före eller efter det att det körs. (Vanligtvis kommer sådana saker att hanteras som en del av skriptet eller funktionen i alla fall.)
Vad är reglerna utan undantag? Ett undantag till ovanstående är privata omfång. Objekt i privata omfång är endast tillgängliga för kommandon som körs inom ramen för vilket de skapades. Ett annat viktigt undantag är objekt som har AllScope-egendomen. Dessa är speciella variabler och aliaser för vilka en förändring i valfri omfattning kommer att påverka alla omfång. Följande kommandon visar vilka variabler och alias som har AllScope-egenskapen:
Get-Variable | Var-Objekt $ _. Alternativ -Match 'AllScope' Get-Alias | Var-Objekt $ _. Alternativ -Match 'AllScope')
Områden i åtgärd
För vår första titt på handlingsplaner, kommer vi att börja i en PowerShell-session där variabeln $ MyVar har ställts till en sträng, "Jag är en global variabel!", Från kommandoraden. Då kommer följande skript att köras från en fil som heter Scope-Demo.ps1:
Funktion FunctionScope 'Ändrar $ MyVar med en funktion.' $ MyVar = 'Jag blev inställd av en funktion!' "MyVar säger $ MyVar" "Kontrollerar nuvarande värde av $ MyVar." "MyVar säger $ MyVar" "Ändra $ MyVar med script." $ MyVar = 'Jag blev inställd av ett manus!' "MyVar säger $ MyVar" "FunctionScope" Kontrollerar slutligt värde för MyVar innan man skriver ut. " "MyVar säger $ MyVar" "
Om PowerShell-skript fungerade på samma sätt som batchskript, förväntar vi oss att $ MyVar (eller% MyVar% i batchsyntax) kommer att växla från "Jag är en global variabel!", Till "Jag har ställts in av ett manus!" , och slutligen till "Jag blev inställd av en funktion!" där det skulle stanna tills det uttryckligen ändras igen eller sessionen avslutas. Men se vad som faktiskt händer här när vi flyttar genom vart och ett av områdena - särskilt efter att FunctionScope-funktionen har slutfört sitt arbete och vi kontrollerar variabeln igen från Script och senare Global, scope.
Som du kan se har variabeln visat sig förändras när vi flyttade genom manuset eftersom, tills funktionen FunctionScope slutfördes, kontrollerade vi variabeln inom samma räckvidd som den senast ändrad. Efter att FunctionScope gjordes skedde vi tillbaka till Script-räckvidden där $ MyVar lämnades orörd av funktionen. Då, när manuset avslutades, kom vi tillbaka till det globala räckvidd där det inte hade modifierats alls.
Nå utanför det lokala området
Så det här är allt bra och bra för att hjälpa dig att oavsiktligt genomföra förändringar i miljön utöver dina skript och funktioner, men vad händer om du faktiskt vill göra sådana ändringar? Det finns en speciell och ganska enkel syntax för att skapa och ändra objekt utanför det lokala området. Du anger bara omfattningsnamnet vid början av variabelnamnet och sätter ett kolon mellan räckvidd och variabla namn. Så här:
$ global: MyVar $ script: MyVar $ local: MyVar
Du kan använda dessa modifierare både när du tittar på och ställer in variabler. Låt oss se vad som händer med det här demonstrationsskriptet:
Funktion FunctionScope "Ändra $ MyVar i det lokala funktionsomfånget ..." $ local: MyVar = "Detta är MyVar i funktionens lokala räckvidd." "Ändra $ MyVar i scriptets omfattning ..." $ script: MyVar = 'MyVar brukade vara inställd av ett skript. Nu inställt av en funktion. "Ändra $ MyVar i det globala räckviddet ..." $ global: MyVar = 'MyVar sattes i det globala räckviddet. Nu ställs in av en funktion. "Kontrollera $ MyVar i varje räckvidd ..." "Lokalt: $ local: MyVar" "Skript: $ script: MyVar" "Global: $ global: MyVar" "" Kommer nuvarande värde av $ MyVar. " "MyVar säger $ MyVar" "Ändra $ MyVar med script." $ MyVar = 'Jag blev inställd av ett manus!' "MyVar säger $ MyVar" FunctionScope "Kontrollerar $ MyVar från scriptsomfattning före avfärd." "MyVar säger $ MyVar" "
Som tidigare börjar vi genom att ställa in variabeln i det globala räckviddet och sluta med att kontrollera det slutliga globala räckviddsresultatet.
Här kan du se att FunctionScope kunde ändra variabeln i Script-räckvidden, och förändringarna fortsätter när den är klar. Även förändringen till variabeln i det globala omfånget fortsatte även efter att skriptet hade gått ut. Detta kan vara särskilt användbart för om du måste upprepade gånger ändra variabler inom ett skript eller inom det globala räckviddet med samma kod. Du definierar bara en funktion eller ett skript som är skrivet för att ändra variabeln var och hur du behöver det, och ring på det närhelst dessa ändringar är nödvändiga.
Som tidigare nämnts kan räckviddsnummer också användas i vissa kommandon för att ändra variabeln på olika nivåer i förhållande till Lokal räckvidd. Här är samma skript som används i det andra exemplet ovan, men med funktionen modifierad för att använda kommandona Get-Variable och Set-Variable med räckvidden istället för att direkt hänvisa variabeln med namnet omfång:
Funktion FunctionScope "Ändrar $ MyVar i räckvidd 0, i förhållande till FunctionScope ..." Set-Variable MyVar "Detta är MyVar i funktionens räckvidd 0." -Scope 0 'Ändrar $ MyVar i räckvidd 1, i förhållande till FunctionScope ...' Set-Variable MyVar 'MyVar ändrades i räckvidd 1, från en funktion.' -Scope 1 'Ändrar $ MyVar i räckvidd 2, i förhållande till Functionscope ...' Set-Variable MyVar 'MyVar ändrades i räckvidd 2, från en funktion.' -Scope 2 "Kontrollerar $ MyVar i varje omfattning ..." Omfattning 0: "Variabel MyVar -Scope 0 -ValueOnly" Scope 1: "Variabel MyVar -Scope 1 -ValueOnly" Scope 2: "Variabel MyVar -Scope 2 -ValueOnly "" Komma nuvarande värde av $ MyVar. " "MyVar säger $ MyVar" "Ändra $ MyVar med script." $ MyVar = 'Jag blev inställd av ett manus!' "MyVar säger $ MyVar" FunctionScope "Kontrollerar $ MyVar från scriptsomfattning före avfärd." "MyVar säger $ MyVar" "
På samma sätt som tidigare kan vi se här hur kommandon i ett räckvidd kan ändra objekt i sitt moderområde.
ytterligare information
Det finns fortfarande mycket mer som kan göras med omfång än vad som passar in i den här artikeln. Scopes påverkar mer än bara variabler, och det finns fortfarande mer att lära sig om privata omfång och AllScope-variablerna. För mer användbar information kan du köra följande kommando från PowerShell:
Få hjälp om_scopes
Samma hjälpfil finns också på TechNet.
Omfattning bild kredit: Spadassin på openclipart