簡體   English   中英

運行腳本塊的 Powershell - 范圍,點源

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM