Some issues with custom functions

by willsteele at 2012-09-10 07:21:03

I am experimenting to see how I would incorporate some of my normal techniques (custom functions) and it took me a little while to get to this point. It seems that any custom functions you need to write (and access in your workflow) must be defined explicitly within the same InlineScript block from which you call the function. So, at this point, I am just throwing ideas and observations out there so folks transitioning from regular scripts to workflow scripts (like me) can see what works, what doesn’t and maybe get some good whys. Feel free to correct me if I am wrong, take it in different directions, share your observations, etc.

workflow test-function {
param(
$first,
$second
)

InlineScript {
function add
{
param(
$a,
$b
)
return $a + $b
}
add -a $using:first -b $using:second
}
}

test-function -first 1 -second 2


When I run this, it, as you might expect, simply returns 3. To demonstrate what happens if you define the function outside of the InlineScript block, look at this example and error:

workflow test-function {
param(
$first,
$second
)

function add
{
param(
$a,
$b
)
return $a + $b
}

InlineScript {
add -a $using:first -b $using:second
}
}

test-function -first 1 -second 2


which gives me this exception:

The term ‘add’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (add:String) , CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : [localhost]


Similarly, if you define the function in a separate InlineScript block, like below, it throws the same error, so, there seems to be no use of InlineScript to organize workflow functionality into chunks. It either goes together or it doesn’t work:

workflow test-function {
param(
$first,
$second
)

InlineScript {
function add
{
param(
$a,
$b
)
return $a + $b
}
}

InlineScript {
add -a $using:first -b $using:second
}
}

test-function -first 1 -second 2
by coderaven at 2012-09-10 07:58:52
I think that this address what DonJ has been saying about not everything not working in workflows and having difficulty setting any guidelines or best practices. Basically, it is a different animal and though it is very powerful in the idea, once you start hitting some issues like this, you have to rethink your approach. There are many of us trying to figure out how, when and where to use these workflows. To get a feel for some restrictions that you have to address, look at this BETA document and see the section titled "PowerShell Language Restrictions in PowerShell Workflow".

Workflows run in their own runspace, this is why you are getting this error. Much like in the past if you were to run a custom script on a remote box using remoting, you would have to define that function in your script block or import the module to get that functionality.
by DonJ at 2012-09-10 10:05:57
Yeah, the deal is that WWF executes each InlineScript in a separate PowerShell instance. Literally, when WWF sees InlineScript, it spins up a copy of PowerShell, feeds it the script, and lets it run. Then the instance goes away. So every InlineScript is absolutely a standalone entity. It can’t see outside itself, and nothing else can see it.

Workflows don’t actually run in a runspace per se; they’re handed off to WWF. Each InlineScript runs in its own runspace, though.

There’s a lot of hackery and trickery we’ll have to master with workflows.
by exomium at 2013-01-11 06:56:03
So actually this does mean:
- I cannot source a script file with custom functions before the scriptfile, which contains my workflow - at least it just doesn’t help, as my functions wouldn’t be there anyway …
- the only things I can use in Workflows are activities or simple script blocks with inlineScript{} - but no "more complex and reuseable functions"

This actually makes the Workflow-Feature much less valuable than it sounds.

@Powershell-devs: wouldn’t it be a good Idea to have a switch for function definitions (much like "[cmdletbinding()]") to make those functions available for workflows?

I’ll probably have to redesign a great number of functions to be workflows, now …
by DonJ at 2013-01-11 07:41:39
PowerShell devs don’t monitor this forum. If you want to make a suggestion, you’d have to file it on Connect.

And you can use custom functions. You just have to do so within an InlineScript. InlineScripts by no means have to be "simple." They can contain entire PowerShell scripts. They can import modules.

And I’ve been saying for months that Workflow has a ton of caveats and isn’t the magical thing that people think it is <grin>.