簡體   English   中英

如何通過引用 Powershell 作業或運行空間傳遞變量?

[英]How to pass variable by reference to Powershell job or runspace?

我有 Powershell 工作。

$cmd = {
  param($a, $b)
  $a++
  $b++
}

$a = 1
$b = 2

Start-Job -ScriptBlock $cmd -ArgumentList $a, $b

如何通過引用傳遞$a$b ,以便在工作完成后更新它們? 或者如何通過引用傳遞變量到運行空間?

在PowerShell中,通過引用傳遞參數總是很尷尬,並且可能無論如何都不適用於PowerShell作業,正如@bluuf所指出的那樣。

我可能會這樣做:

$cmd = {
    Param($x, $y)
    $x+1
    $y+1
}

$a = 1
$b = 2

$a, $b = Start-Job -ScriptBlock $cmd -ArgumentList $a, $b |
         Wait-Job |
         Receive-Job

上面的代碼將變量$a$b傳遞給scriptblock,並在收到作業輸出后將修改后的值賦給變量。

我剛寫的簡單示例(不介意凌亂的代碼)

# Test scriptblock
$Scriptblock = {
param([ref]$a,[ref]$b)
$a.Value = $a.Value + 1
$b.Value = $b.Value + 1
}

$testValue1 = 20 # set initial value
$testValue2 = 30 # set initial value

# Create the runspace
$Runspace = [runspacefactory]::CreateRunspace()
$Runspace.ApartmentState = [System.Threading.ApartmentState]::STA
$Runspace.Open()
# create the PS session and assign the runspace
$PS = [powershell]::Create()
$PS.Runspace = $Runspace

# add the scriptblock and add the argument as reference variables
$PS.AddScript($Scriptblock)
$PS.AddArgument([ref]$testValue1)
$PS.AddArgument([ref]$testValue2)

# Invoke the scriptblock
$PS.BeginInvoke()

運行此之后,測試值會更新,因為它們是由ref傳遞的。

帶有示例的更全面的腳本。

  • 它還應該包括傳遞$host或其他東西的能力,從傳遞的腳本 output 到控制台創建write-host 但我沒有時間弄清楚如何做到這一點。
$v = 1

function newThread ([scriptblock]$script, [Parameter(ValueFromPipeline)]$param, [Parameter(ValueFromRemainingArguments)]$args) {
    process {
        $Powershell = [powershell]::Create()
        $Runspace = [runspacefactory]::CreateRunspace()
        
        # allows to limit commands available there
        # $InitialSessionState = InitialSessionState::Create()
        # $Runspace.InitialSessionState = $InitialSessionState
        
        $Powershell.Runspace = $Runspace

        $null = $Powershell.AddScript($script)
        $null = $Powershell.AddArgument($param)
        foreach ($v_f in $args) {
            $null = $Powershell.AddArgument($v_f)
        }

        $Runspace.Open()
        $Job = $Powershell.BeginInvoke()
        
        [PSCustomObject]@{
            Job=$Job
            Powershell=$Powershell
        }
    }
}

$script = {
    param([ref]$v,$v2)
    $v.Value++
    $v2
}
$thread = newThread $script ([ref]$v) 3

do {} until ($thread.Job.IsCompleted)
$v1 = $thread.Powershell.EndInvoke($thread.Job)
$thread.Powershell.Dispose()

write-host "end $($v,$v1[0])"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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