codememo

시작 작업의 매개 변수 중 하나로 스크립트 블록을 전달하려면 어떻게 해야 합니까?

tipmemo 2023. 9. 25. 22:47
반응형

시작 작업의 매개 변수 중 하나로 스크립트 블록을 전달하려면 어떻게 해야 합니까?

스크립트 블록을 실행하는 백그라운드 작업을 생성하려고 합니다.이 스크립트 블록을 매개 변수로 전달해야 하는데 구문이 작동하지 않는 것 같습니다.스크립트 블록이 도중 어딘가에서 문자열로 변환되고 있습니다.

스크립트 블록을 로컬 함수로 전달할 때는 잘 작동하지만 시작 작업을 통해서는 작동하지 않습니다.

다음 구문이 작동합니다.

function LocalFunction
{
    param (
        [parameter(Mandatory=$true)]
        [ScriptBlock]$ScriptBlock
    )

    &$ScriptBlock | % { echo "got $_" }
}

LocalFunction -ScriptBlock { echo "hello" }

이 출력은 예상대로 "안녕하세요"를 출력합니다.

그러나 다음은 실패합니다.

$job = start-job -argumentlist { echo "hello" } -scriptblock {
    param (
        [parameter(Mandatory=$true)]
        [ScriptBlock]$ScriptBlock
    )
    &$ScriptBlock | % { echo "got $_" }
}
start-sleep -s 1
receive-job $job

이것이 반환하는 오류는

Receive-Job : Cannot process argument transformation on parameter 'ScriptBlock'. Cannot convert the " echo "hello" " value of type "System.String" to type "System.Management.Automation.ScriptBlock".

따라서 오류를 제대로 읽고 있으면 -argumentlist가 인수를 문자열로 강제하고 있는 것처럼 보입니다.

이를 해결하는 한 가지 방법은 스크립트 블록 코드를 문자열로 전달한 다음 작업 내부의 문자열에서 스크립트 블록을 생성하여 실행하는 것입니다.

Start-Job -ArgumentList "write-host hello"  -scriptblock {

    param (
        [parameter(Mandatory=$true)][string]$ScriptBlock
    )

    & ([scriptblock]::Create($ScriptBlock))

} | Wait-Job | Receive-Job

오늘은 이게 되는 것 같네요.

function LocalFunction
{
    param
    (
        [scriptblock] $block
    )

    $block.Invoke() | % { "got $_" }
}

LocalFunction { "Hello"} 

제 실험에 따르면, PowerShell은 스크립트 블록을 전달할 때에도 객체[]인 ArgumentList를 문자열로 구문 분석하고 있습니다.다음 코드:

$job = start-job -scriptblock { $args[0].GetType().FullName } -argumentlist { echo "hello" }
start-sleep -s 1
receive-job $job

결과는 다음과 같습니다.

시스템. 문자열

내가 알기로는, 여기서 유일한 해결책은 Shay's뿐이지만, 이 경우 PowerShell이 스크립트 블록을 문자열로 구문 분석하므로 -ArgumentList를 문자열로 전달할 필요는 없습니다.

문자열로 읽고 스크립트 블록으로 변환해야 합니다.

Powershell v1에서는 다음을 수행할 수 있습니다.

$ScriptBlock = $executioncontext.invokecommand.NewScriptBlock($string)

그리고 powershell v2에서는 다음을 수행할 수 있습니다.

$ScriptBlock = [scriptblock]::Create($string)

당신의 코드는 다음과 같습니다.

function LocalFunction
{
    param (
        [parameter(Mandatory=$true)]
        $ScriptBlock
    )

    $sb = [scriptblock]::Create($ScriptBlock)

    $sb | % { echo "got $_" }
}

LocalFunction -ScriptBlock "echo 'hello'"

' [스크립트 블록]::Create($ScriptBlock)'는 문자열 주변에 곱슬곱슬한 가새를 배치하여 스크립트 블록을 만듭니다.

여기 http://get-powershell.com/post/2008/12/15/ConvertTo-ScriptBlock.aspx 에서 정보를 찾습니다.

따라서 인라인 스크립트 블록을 삽입하고자 한다면 Shay의 솔루션(주목한 바와 같이)이 가장 적합할 것입니다.반면, 단순히 스크립트 블록을 매개 변수로 전달하려는 경우에는 다음과 같은 유형의 변수를 사용하는 것을 고려해 보십시오.scriptblock그 다음에 그것을 그 가치로 전달합니다.-ScriptBlock매개 변수.

function LocalFunction
{
    param (
        [parameter(Mandatory=$true)]
        [ScriptBlock]$ScriptBlock
    )

    &$ScriptBlock | % { echo "got $_" }
}

[scriptblock]$sb = { echo "hello" }

LocalFunction -ScriptBlock $sb

언급URL : https://stackoverflow.com/questions/11844390/how-do-i-pass-a-scriptblock-as-one-of-the-parameters-in-start-job

반응형