![](/img/trans.png)
[英]Putting functions in separate script and dot-sourcing them - what will the scope be
[英]Powershell running a scriptblock - scope, dot-sourcing
我想編寫一個函數,該函數接受一個腳本塊作為參數,並在調用它的范圍內執行該腳本塊。
Measure-Command 是我想要的行為的一個例子。 腳本塊在與 Measure-Command 本身相同的范圍內運行。 如果腳本塊引用了此范圍內的變量,則腳本可以更改它。
附件是一個示例腳本塊,它增加了 $a 變量。 當被 Measure-Command 調用時,變量會增加。 但是當被 Wrapper 函數調用時,變量不會增加——除非我對 Wrapper 函數的調用和 Wrapper 函數本身都使用點源。
function Wrapper1
{
param( $scriptBlock )
$startTime = Get-Date
Write-Output ( "{0:HH:mm:ss} Start script" -f $startTime )
& $scriptBlock
$endTime = Get-Date
Write-Output ( "{0:HH:mm:ss} End script - {1:c} seconds elapsed" -f $endTime, ( $endTime - $StartTime ) )
}
function Wrapper2
{
param( $scriptBlock )
$startTime = Get-Date
Write-Output ( "{0:HH:mm:ss} Start script" -f $startTime )
. $scriptBlock
$endTime = Get-Date
Write-Output ( "{0:HH:mm:ss} End script - {1:c} seconds elapsed" -f $endTime, ( $endTime - $StartTime ) )
}
$a = 1
Write-Output "Initial state: `$a = $a"
Measure-Command { $a++ } | Out-Null
Write-Output "Measure-Command results: `$a = $a"
Wrapper1 { $a++ }
Write-Output "Wrapper1 results: `$a = $a"
. Wrapper1 { $a++ }
Write-Output "dot-sourced Wrapper1 results: `$a = $a"
Wrapper2 { $a++ }
Write-Output "Wrapper2 results: `$a = $a"
. Wrapper2 { $a++ }
Write-Output "dot-sourced Wrapper2 results: `$a = $a"
運行這段代碼的結果是:
Initial state: $a = 1
Measure-Command results: $a = 2
13:44:49 Start script
13:44:49 End script - 00:00:00 seconds elapsed
Wrapper1 results: $a = 2
13:44:49 Start script
13:44:49 End script - 00:00:00.0157407 seconds elapsed
dot-sourced Wrapper1 results: $a = 2
13:44:49 Start script
13:44:49 End script - 00:00:00 seconds elapsed
Wrapper2 results: $a = 2
13:44:49 Start script
13:44:49 End script - 00:00:00 seconds elapsed
dot-sourced Wrapper2 results: $a = 3
雖然最后一個選項有效,但我想避免調用 Wrapper2 的點源語法。 這可能嗎? Measure-Command 不使用點源語法,所以它似乎是可能的。
PetSerAl ,正如他慣常做的那樣,在對這個問題的簡短評論中提供了關鍵的指針:
將函數放在module 中,以及腳本塊參數的點源調用,解決了這個問題:
$null = New-Module {
function Wrapper {
param($ScriptBlock)
. $ScriptBlock
}
}
$a = 1
Wrapper { $a++ }
$a
以上產生2
,證明腳本塊在調用者的范圍內執行。
有關為什么這樣做以及為什么有必要的解釋,請參閱相關問題的答案。
注意:上面的方法沒有擴展到管道使用,在那里你需要傳遞腳本塊,這些腳本塊期望使用自動變量$_
來引用手頭的對象(例如,
1, 2, 3 | Wrapper { $_ ... }
1, 2, 3 | Wrapper { $_ ... }
; 為了支持此用例,需要一種解決方法 - 請參閱此答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.