2016-04-14 33 views
4

The 我使用的腳本Microsoft.PowerShell_profile.ps1運行時會創建很多變量。我已將所有變量的範圍設置爲「腳本」,但腳本中使用的變量永遠不會超出範圍。Powershell Profile腳本點源?

我希望一旦腳本完成運行並將控制權交給我後,變量就會超出範圍。

如果我比較了全局變量,本地變量和腳本變量的數量,我想出了相同的數字。

例子:

# 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 

目前,我捕捉變量的快照我的配置腳本的開頭,然後在最後刪除任何新的變數。

例子:

$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

我不確定你的目標。爲什麼要將變量的範圍設置爲'script'? –

+0

@Bill_Stewart:意圖是在配置文件內部使用臨時變量,一旦配置文件加載完成後,暫時變量不應該留下。 – mklement0

+1

啊。是的,PowerShell配置文件是點源。 –

回答

2

是,PowerShell配置文件是點源設計,因爲這是使其中所含的定義(別名,函數,...)是全球可用默認 - 這畢竟是配置文件的主要目的。

不幸的是,沒有範圍修改,允許你創建一個變量臨時範圍內,你只希望存在,而輪廓裝載 - 即使是範圍local在配置文件腳本有效全球;同樣,使用範圍private也不是一個選項,因爲配置文件的腳本範圍 - 由於是點源 - 是全球範圍的

一般來說,你可以使用&(電話運營商)用一個腳本塊,以創建範圍限定於該塊是塊中的變量,但通常是有分歧與在配置文件創建全球可用定義,至少在默認情況下。
同樣,如果在自己的答案中調用另一個沒有點源的腳本,則默認情況下不會使其全局可用。
可以,然而,通過指定全球範圍內創建 -dot來源的腳本塊/腳本全局元素明確;例如:& { $global:foo = 'Going global' }& { function global:bar { 'global func' } }

這就是說,後面點採購型材的理由可能是,它更容易使默認所有定義全球,使得輪廓的典型元素的定義 - 別名,功能,驅動器映射,加載模塊 - 更簡單(不需要指定明確的範圍)。
相比之下,全局變量不太典型,爲了定義上面列出的典型元素,您通常不需要配置文件中的腳本級變量(因此全局變量)。


如果您還需要在您的配置文件來創建(概念)臨時變量(這是創建全局可用的別名,函數,...的要求):

一個簡單的解決方法在配置文件腳本中使用外來變量名稱前綴(如__)以降低其意外引用(例如,$__profileVar1 = ...)的風險。
換句話說:變量仍然全球存在,但他們的異國名稱通常不會導致問題。

然而,你的方法,儘管它需要一些額外的工作,聽起來像一個可靠的替代方法,這裏是什麼樣子全(使用PSv3 +語法):

# 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 

注意我依靠Compare-Object的默認行爲只報告對象之間的差異,假設你還沒有試過刪除任何變量,只有變量是重新移植。


注意的是,雖然它可以從他們確實是點源輪廓文件的實際行爲推斷 - 因爲點採購是將元素添加到當前作用域的唯一途徑(全球範圍,在配置文件的情況下) - 這個事實並不明確記錄本身。

下面是各種幫助主題片段(如PSv5的),提供線索(重點煤礦):

Get-Help about_Profiles

Windows PowerShell配置文件是運行在Windows PowerShell中 腳本開始。 您可以使用該配置文件作爲登錄腳本來自定義 環境。您可以添加命令,別名,函數,變量,管理單元, 模塊和Windows PowerShell驅動器。您也可以將其他 特定於會話的元素添加到您的配置文件中,以便在每個會話中都可用,而無需導入或重新創建它們。

Get-Help about_Variables

默認情況下,變量僅在 創建它們的範圍是可用的。

例如,您在函數中創建的變量爲 僅在該函數中可用。 在腳本中創建的變量僅在腳本中可用(,除非 用點源代碼將該腳本添加到當前範圍)。

Get-Help about_Operators

。點源操作員 在當前範圍內運行腳本,以便將腳本創建的所有功能, 別名和變量添加到當前的 範圍內。

Get-Help about_Scopes

但是,可以使用點 源符號添加腳本或者函數到當前範圍。然後,當腳本在當前作用域中運行時,腳本創建的任何 函數,別名和變量在當前作用域中可用 。

要將函數添加到當前作用域,請在函數調用中函數的路徑和名稱前輸入一個點(。)和空格。

+0

謝謝您的回答,併爲了更好地回答問題而修改答案。你做得很好。讓我指出一個問題,我發現我以前的解決方法(使用快照和比較對象)。當我加載一個模塊,並創建一個全局變量。這個變量稍後會被這個操作刪除。這就是爲什麼我正在尋求一種「更好的方式」來做到這一點,並希望適當的範圍能夠解決它。再次感謝你! –

+0

我也很好奇,如果你有第一段的源代碼**「PowerShell配置文件是由設計點源的,因爲這就是允許其中包含的定義(別名,函數......)在全球範圍內可用」* *。 –

+0

感謝指針重新加載模塊 - 我已經更新了一個警告的答案。您仍然可以使用該技術,只需在加載模塊並點擊其他腳本之後仔細放置可變快照獲取命令即可。我也很好奇你在配置文件中實際做了些什麼,如果它適合你簡單地用'&'調用另一個腳本,它不能創建_global_元素。 – mklement0

0

所以它聽起來像Powershell點源的配置文件。我找不到特別說明的資源,或者其他提出此問題的論壇。

我找到了答案,並且想在此發佈。

我已將我的配置文件更改爲只調用腳本文件。腳本現在有自己的範圍,只要變量不是全局變量,一旦配置文件加載完成,它們就會超出範圍。

所以現在我的個人資料已經一行:

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

Microsoft.PowerShell_profile_v2.ps1現在可以包含適當範圍:

$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." 

這是什麼允許,是天寒腳本導入包含全局變量的模塊。這些變量在本屆會議期間將繼續存在。

我仍然很好奇爲什麼微軟決定以這種方式調用配置文件。如果有人知道,並希望分享。我很想在這裏看到答案。

+1

mklement0已經爲您的問題提供了答案。這些配置文件是點源的,因此定義可在全球範圍內使用。 –

+0

我開始看到你來自哪裏:你關注的是全局_variables_,然而,它並不是典型的 元素放置在配置文件中;定義別名,函數和驅動器映射,以及加載模塊/管理單元更爲典型。 因此,將這些元素設置爲global_by default_(通過點源)比在任何時候指定一個範圍更方便。 相反,問題是:爲什麼您需要在配置文件中定義腳本級變量? 爲了創建上述典型元素,您不需要腳本級別的變量。 – mklement0