7

How can I call a function in a workflow from a nested InlineScript? The following throws an exception because the function is out of scope in the InlineScript:

Workflow test
{
    function func1
    {
        Write-Verbose "test verbose" -verbose
    }

    InlineScript
    {
        func1
    }
}
test
David Klempfner
  • 8,700
  • 20
  • 73
  • 153

2 Answers2

3

"The inlinescript activity runs commands in a standard, non-workflow Windows PowerShell session and then returns the output to the workflow."

Read more here.

Each inlinescript is executed in a new PowerShell session, so it has no visibility of any functions defined in the parent workflow. You can pass a variable to workflow using the $Using: statement,

workflow Test
{
    $a = 1

    # Change the value in workflow scope usin $Using: , return the new value.
    $a = InlineScript {$a = $Using:a+1; $a}
    "New value of a = $a"
}   

Test

PS> New value of a = 2

but not a function, or module for that mater.

Jan Chrbolka
  • 4,184
  • 2
  • 29
  • 38
  • 1
    A somewhat functional alternative is to assign your ScriptBlock to a variable instead of a function, which can then be accessed via the `$using:` feature, and caused to execute with the `Invoke` method. `$funct1 = {write-verbose "Hello world" -verbose};inlinescript{$using:funct1.invoke()}` – TheMadTechnician Apr 24 '15 at 04:58
  • @TheMadTechnician One can't call a member with a $Using:variable; one would need to assign it to a local variable then call the member. Also, the function would serialize and deserialize as just the function name, not the function itself. The only way to really to do this is something like this would be to get the function definition, pass it into the workflow, and use [ScriptBlock]::Create($Using:func1).Invoke(). This is also fraught with issues - if the function definition called other functions they would not be in scope either. The only way to reuse functions is through a custom module. – rshadman Oct 12 '18 at 00:47
0

In the past I used the technique where I put all the common stuff in powershell module file, and do:

workflow Hey
{
   PrepareMachine
   ConfigureIIS
}

function PrepareMachine() {
  Import-Module "MyCommonStuff"
  CallSomethingBlahBlah()
}

function ConfigureIIS {
  Import-Module "MyCommonStuff"
  CallSomethingBlahBlah2()
}

You don't even have to wrap it in a module, you could just define the function out of workflow, and it would still work:

workflow Hey 
{
   InlineScript {
     func1
  }
}

function func1 {
  Write-Output "Boom!"
}

That said, I was not impressed by workflows at all. Seems like quite pointless feature if you ask me. The most useful stuff about workflows is the ability to run things in parallel, but jobs can do it too. The idea above rant is that make sure you really do need workflows :)

Erti-Chris Eelmaa
  • 25,338
  • 6
  • 61
  • 78
  • Your comment helped me quickly abandon my struggles getting Workflows working and go to jobs, which seem to fit in a lot better with the rest of PowerShell. Thanks. – makhdumi Nov 17 '15 at 22:25