2016-04-14 5 views
4

Das Skript Microsoft.PowerShell_profile.ps1, das ich verwende, erstellt eine Menge Variablen, wenn es ausgeführt wird. Ich habe den Gültigkeitsbereich aller Variablen auf "Skript" gesetzt, aber die Variablen, die im Skript verwendet werden, gehen niemals außer Reichweite.Sind Powershell-Profilskripte dot-source?

Ich möchte, dass die Variablen out-of-scope gehen, sobald das Skript ausgeführt wird und die Steuerung an mich übergeben wird.

Wenn ich die Anzahl der globalen, lokalen und Script-Variablen, die ich habe, vergleiche, bekomme ich die gleiche Nummer.

Beispiel:

# Profile script does what it does. 

Get-Variable -Scope Global | Measure-Object 
Get-Variable -Scope Local | Measure-Object 
Get-Variable -Scope Script | Measure-Object 

Output: 
60 
60 
60 

Derzeit bin ich eine Momentaufnahme der Variablen am Anfang meines Profils Skript festzuhalten und dann am Ende alle neuen Variablen zu entfernen.

Beispiel:

$snapshotBefore = Get-Variable 
$profileVar1 = 'some value' 
$profileVar2 = 'some other value' 
$snapshotAfter = Get-Variable 

# Compare before and after, and create list of new variables. 

Remove-Variable $variablesToRemove 
+0

Ich bin mir Ihres Ziels nicht sicher. Warum legen Sie die Gültigkeitsbereiche der Variablen auf "script" fest? –

+0

@Bill_Stewart: Die Absicht besteht darin, temporäre Variablen innerhalb des Profils zu verwenden, die nicht länger verweilen sollten, sobald das Profil geladen wurde. – mklement0

+1

Ah. Ja, PowerShell-Profile sind dot-sourcing. –

Antwort

2

Ja, Powershell-Profile sind dot-sourced nach Design, denn das ist, was die Definitionen in ihnen enthaltenen erlaubt (Aliase, Funktionen, ...) zu sein global verfügbar standardmäßig - das ist schließlich der Hauptzweck der Profildateien.

Leider gibt es keinen Spielraum Modifikator, dass Sie einen temporären Raum für Variablen erstellen können Sie nur wollen existieren, während das Profil ist Laden - auch Umfang local effektiv global in einem Profil Skript; In ähnlicher Weise ist die Verwendung des Bereichs private auch keine Option, da der Skriptbereich des Profils - aufgrund der Punktquelle - der globale Bereich ist.

Generell Sie & (der Anruf Operator) mit einem Skriptblock verwenden können Variablen innerhalb dieses Blockes zu erzeugen, die zu diesem Block scoped sind, aber das ist in der Regel im Widerspruch zu global verfügbaren Definitionen in einem Profil zu erstellen, zumindest standardmäßig.
Wenn Sie ein anderes Skript aufrufen, ohne es zu dot-sourcing, wie in Ihrer eigenen Antwort, werden seine Definitionen standardmäßig nicht global verfügbar gemacht. jedoch
Sie können, erstellen globale Elemente aus nicht -dot-sourced Skriptblöcke/script durch den globalen Bereich Angabe ausdrücklich; beispielsweise: & { $global:foo = 'Going global' } oder & { function global:bar { 'global func' } }.

Das heißt, die Logik hinter Dot-Sourcing-Profile ist wahrscheinlich, dass es einfacher ist, alle Definitionen global standardmäßig zu machen, die Definition von typischen Elemente eines Profils zu machen - Aliase, Funktionen, Laufwerkszuordnungen, Laden von Modulen - einfacher (es muss kein expliziter Bereich angegeben werden).
Im Gegensatz dazu sind globale Variablen weniger typisch, und um die oben aufgeführten typischen Elemente zu definieren, benötigen Sie normalerweise keine Variablen auf Skript-Ebene (und somit global) in Ihrem Profil.


Wenn Sie noch (Konzept) temporäre Variablen in Ihrem Profil zu erstellen (die nicht ist eine Voraussetzung für die global verfügbare Aliase erstellen, Funktionen, ...):

A einfache Abhilfe ist Verwenden Sie einen exotischen Variablennamen Präfix wie __ innerhalb des Profilskripts, um das Risiko zu reduzieren, dass sie durch einen Unfall referenziert werden (z. B. $__profileVar1 = ...).
Mit anderen Worten: die Variablen noch existieren weltweit, aber ihre exotischen Namen werden in der Regel keine Probleme verursachen.

jedoch Ihr Ansatz, auch wenn es ein wenig zusätzliche Arbeit erfordert, klingt wie eine robuste Abhilfe, hier ist, wie es in voller aussieht (mit PSV3 + Syntax):

# Save a snapshot of current variables. 
# * If there are variables that you DO want to exist globally, 
# define them ABOVE this command. 
# * Also, load MODULE and dot-source OTHER SCRIPTS ABOVE this command, 
# because they may create variables that *should* be available globally. 
$varsBefore = (Get-Variable).Name 

# ... define and use temporary variables 

# Remove all variables that were created since the 
# snapshot was taken, including $varsBefore. 
Remove-Variable (Compare-Object $varsBefore (Get-Variable).Name).InputObject 

Beachten Sie, dass ich verlasse mich auf Compare-Object ‚s Standardverhalten von nur Unterschiede Berichterstattung zwischen Objekten und, vorausgesetzt, Sie haben nicht versucht, alle Variablen entfernen, nur die Variablen hinzugefügt sind re portiert.


Beachten Sie, dass, während es aus dem tatsächlichen Verhalten der Profildateien geschlossen werden kann, dass sie in der Tat punkt bezogen sind - vorausgesetzt, dass Dot-Sourcing ist die einzige Art und Weise Elemente auf den aktuellen Bereich hinzuzufügen (die globale Geltungsbereich, im Falle von Profilen) - diese Tatsache ist nicht explizit dokumentiert als solche.

Hier sind Auszüge aus verschiedenen Hilfethemen (Stand pSV5), die Hinweise darauf geben (Hervorhebung von mir):

Von Get-Help about_Profiles:

Ein Windows Powershell-Profil ist ein Skript, das ausgeführt wird, wenn Windows Powershell beginnt. Sie können das Profil als Anmeldeskript verwenden, um die -Umgebung anzupassen. Sie können Befehle, Aliase, Funktionen, Variablen, Snap-Ins, Module und Windows PowerShell-Laufwerke hinzufügen. Sie können Ihrem Profil auch andere sitzungsspezifische Elemente hinzufügen, sodass sie in jeder Sitzung verfügbar sind, ohne sie importieren oder neu erstellen zu müssen.

Von Get-Help about_Variables:

sind standardmäßig Variablen nur in dem Umfang, in dem sie erstellt werden.

Zum Beispiel ist eine Variable, die Sie in einer Funktion erstellen, nur innerhalb der Funktion verfügbar. Eine Variable, die Sie in einem Skript erstellen, ist nur innerhalb des Skripts verfügbar (, es sei denn Sie dot-source das Skript, das es zum aktuellen Gültigkeitsbereich hinzufügt).

Von Get-Help about_Operators:

. Dot-Sourcing-Operator Führt ein Skript im aktuellen Bereich aus, sodass alle Funktionen, Aliase und Variablen, die das Skript erstellt, zum aktuellen Bereich hinzugefügt werden.

Von Get-Help about_Scopes

Aber können Sie ein Skript oder Funktion auf den aktuellen Bereich hinzufügen, indem Punkt Quelle Notation. Wenn ein Skript im aktuellen Bereich ausgeführt wird, sind Funktionen, Aliasnamen und Variablen, die das Skript erstellt, im aktuellen Gültigkeitsbereich verfügbar.

Um dem aktuellen Bereich eine Funktion hinzuzufügen, geben Sie einen Punkt (.) Und ein Leerzeichen vor den Pfad und den Namen der Funktion im Funktionsaufruf ein.

+0

Vielen Dank für Ihre Antwort und für die Änderung Ihrer Antwort, um die Frage besser zu beantworten. Du hast einen guten Job gemacht. Lassen Sie mich auf ein Problem hinweisen, das ich bei meiner vorherigen Problemumgehung gefunden habe (mit Snapshots und Compare-Object). Wenn ich ein Modul geladen habe und eine globale Variable erstellt habe. Diese Variable wird später durch diese Operation entfernt. Aus diesem Grund suchte ich nach einem "besseren Weg" und hoffte, dass das richtige Scoping das Problem lösen würde. Danke nochmal! –

+0

auch ich war neugierig, ob Sie eine Quelle für Ihren ersten Absatz hatten ** "PowerShell-Profile sind dot-sourcing von Design, weil das ist, was ermöglicht die Definitionen in ihnen enthalten (Aliase, Funktionen, ...) global verfügbar sein" * *. –

+0

Danke für die Pointer Re Lademodule - Ich habe die Antwort mit einem Vorbehalt aktualisiert. Sie können diese Technik weiterhin verwenden. Sie müssen den Befehl zum Erstellen eines Snapshot-Snapshots nur nach dem Laden von Modulen und dem Dot-Sourcing anderer Scripts durchführen. Ich bin auch neugierig, was Sie in Ihrem Profil tun, wenn es für Sie einfach ist, ein anderes Skript mit '&' aufzurufen, das _global_ Elemente nicht erzeugen kann. – mklement0

0

So klingt es wie PowerShell dot-sources das Profil. Ich konnte keine Ressource finden, die das ausdrücklich sagt, oder andere Foren, die diese Frage gestellt haben.

Ich habe eine Antwort gefunden und wollte sie hier posten.

Ich habe mein Profil geändert, um nur eine Skriptdatei aufzurufen. Das Skript hat jetzt seinen eigenen Gültigkeitsbereich, und solange die Variablen nicht global sind, werden sie nach dem Laden des Profils aus dem Gültigkeitsbereich fallen.

So jetzt mein Profil hat einzeilige:

& (Split-Path $Path $profile -Parent | Join-Path "Microsoft.PowerShell_profile_v2.ps1") 

Microsoft.PowerShell_profile_v2.ps1 nun eigentlichen Umfang enthalten:

$Global:myGlobalVar = "A variable that will be available during the current session" 
$Script:myVar = "A variable that will disappear after script finishes." 
$myVar2 = "Another variable that will disappear after script finishes." 

Was dies ermöglicht, ist für das Profil-Skript Importieren Sie Module, die globale Variablen enthalten. Diese Variablen bleiben während der aktuellen Sitzung bestehen.

Ich wäre immer noch neugierig, warum Microsoft entschied, das Profil auf diese Weise aufzurufen. Wenn jemand weiß, und möchte teilen. Ich würde gerne die Antwort hier sehen.

+1

mklement0 hat bereits die Antwort auf Ihre Frage gegeben. Die Profile sind dot-sourcing, so dass die Definitionen global verfügbar sind. –

+0

Ich fange an zu sehen, woher du kommst: du konzentrierst dich auf globale _variables_, die jedoch _nicht_ das typische Element sind, das in einem Profil platziert werden soll; Das Definieren von Aliasen, Funktionen und Laufwerkszuordnungen sowie das Laden von Modulen/Snap-Ins ist wesentlich typischer. Daher ist es bequemer, diese Elemente global _by default_ zu haben - via Dot-Sourcing - als immer einen Bereich anzugeben. Umgekehrt lautet die Frage: Warum müssen Sie in Ihrem Profil Variablen auf Skript-Ebene definieren? Um die oben genannten typischen Elemente zu erstellen, benötigen Sie _nicht_ Variablen auf Script-Ebene. – mklement0