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)

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

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

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

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

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

Я немного покопался, и похоже, что кто-то уже ответил на этот тип вопроса здесь. По сути, аргументы для заданий и удаленных команд сериализованы. ScriptBlock выходит на другом конце как String. Просто вызовите $func = [ScriptBlock]::Create($func), чтобы преобразовать эту строку обратно в SB и вызвать как обычно.

RiverHeart 26.11.2018 02:43

@RiverHeart В конце концов, ваш комментарий мне действительно помог. Добавь свой ответ Я одобряю =)

sheldonzy 27.11.2018 15:39
Что такое компоненты React? Введение в компоненты | Типы компонентов
Что такое компоненты React? Введение в компоненты | Типы компонентов
Компонент - это независимый, многократно используемый фрагмент кода, который делит пользовательский интерфейс на более мелкие части. Например, если мы...
0
2
4 227
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Start-Job  -Name "currentJob" -ArgumentList $name - ScriptBlock ${function:foo}

Я посмотрю на твой ответ завтра подробно, но от быстрого бега не получается. Звонок по-прежнему $j1 = mainFunction -name "output!" -moveFunction $Function:foo?

sheldonzy 26.11.2018 09:42

Можно даже Start-Job -Name "currentJob" -ArgumentList $name, $Function:foo - ScriptBlock $SB

Prasoon Karunan V 26.11.2018 13:39

Мой комментарий сверху никто не читал? :( Это не работает, потому что блок сценария сериализуется и выводится в виде строки при передаче в задание. Вам нужно взять эту строку и сгенерировать новый блок сценария.

RiverHeart 26.11.2018 23:14

ага, де-сериализуется, не заметил вашего комментария.

Prasoon Karunan V 27.11.2018 07:30

@sheldonzy: вы можете напрямую вызывать функцию в задании.

Prasoon Karunan V 27.11.2018 07:31
Ответ принят как подходящий

Просто повторение моего предыдущего комментария плюс пример кода. Похожая проблема здесь. По сути, аргументы, передаваемые командам 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

Другие вопросы по теме