Аргумент функции вызова Powershell Start-job с параметром

У меня есть функция mainFunction, которая получает 2 параметра: $name будет обычной строкой, а $moveFunction будет какой-то функцией.

Я хочу запустить задание ScriptBlock ($SB), которое будет вызывать $moveFunction с $name в качестве аргумента.

function foo($a){
    Write-Output "In function foo with the argument => $a"
}

$SB = { 
        param($C, $fooFunction)
        $fooFunction.Invoke($C)
     } 

function mainFunction($name, $moveFunction){
    Start-Job  -Name "currentJob" -ArgumentList $name, ${Function:$moveFunction} -ScriptBlock $SB

}


$j1 = mainFunction -name "output!" -moveFunction $Function:foo

Я проверил, что $moveFunction уже существует в mainFunction ($moveFunction.invoke(5) в mainFunction)

Я не могу найти проблему в передаче функции в качестве аргумента в start-job.

и из Get-Job -Name "CurrentJob" | Receive-Job я получаю:

You cannot call a method on a null-valued expression.
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
    + PSComputerName        : localhost

Любая помощь будет оценена по достоинству.

edit: проблема, скорее всего, в том, как я передаю функцию в качестве аргумента (${Function:$moveFunction}


person sheldonzy    schedule 25.11.2018    source источник
comment
Я немного поковырялся, и похоже, что кто-то уже ответил на этот тип вопроса здесь. По сути, аргументы для заданий и удаленных команд сериализуются. ScriptBlock выходит с другого конца как строка. Просто вызовите $func = [ScriptBlock]::Create($func), чтобы преобразовать эту строку обратно в правильный SB и вызвать как обычно.   -  person RiverHeart    schedule 26.11.2018
comment
@RiverHeart В конце концов, ваш комментарий действительно помог мне. Добавьте свой ответ, я одобрю его =)   -  person sheldonzy    schedule 27.11.2018


Ответы (2)


Просто перефразировка моего предыдущего комментария плюс пример кода. Аналогичная проблема здесь. По сути, аргументы, передаваемые командам Jobs и Remote, сериализуются. В процессе десериализации функции и блоки скриптов выводятся в виде строк, а не их исходного типа. К счастью, преобразовать их в вызываемые блоки сценариев с помощью [ScriptBlock]::Create("string") несложно.

function foo {
    write-host "foo"
}

function bar {
    # This argument comes in as a string
    param($func)
    write-host "bar"

    # Create scriptblock from string
    $func = [ScriptBlock]::Create($func)
    $func.invoke()
}

Start-Job -ArgumentList $Function:Foo -ScriptBlock $Function:Bar

Get-Job | Wait-job
Get-Job | Receive-job
person RiverHeart    schedule 27.11.2018

Вы передаете одну и ту же функцию и вызываете ее. Вы можете напрямую использовать функцию в задании.

Start-Job  -Name "currentJob" -ArgumentList $name - ScriptBlock ${function:foo}
person Prasoon Karunan V    schedule 26.11.2018
comment
Завтра посмотрю ваш ответ на глубине, но с быстрого бега не идет. Вызов по-прежнему $j1 = mainFunction -name "output!" -moveFunction $Function:foo ? - person sheldonzy; 26.11.2018
comment
Вы даже можете Start-Job -Name "currentJob" -ArgumentList $name, $Function:foo - ScriptBlock $SB - person Prasoon Karunan V; 26.11.2018
comment
Неужели никто не читал мой комментарий сверху? :( Это не работает, потому что блок скрипта сериализуется и выходит в виде строки при передаче в задание. Вам нужно взять эту строку и сгенерировать новый блок скрипта. - person RiverHeart; 27.11.2018
comment
да, он десериализуется, я не заметил вашего комментария. - person Prasoon Karunan V; 27.11.2018
comment
@sheldonzyyou может напрямую вызывать функцию в задании. - person Prasoon Karunan V; 27.11.2018