Quantcast
Channel: Service Management Automation – Trond's Working!
Viewing all articles
Browse latest Browse all 9

Powershell Workflow peculiarities #1: Parameter naming when calling sub-worfklows/sub-runbooks

$
0
0

Update: I got feedback from several PowerShell MVPs that the problem I encounter below is caused by using a parameter named “id” (Thanks Alexandar and Jan Egil). So, never ever use “id” as a parameter in PowerShell workflows, and you’ll save yourself hours of head-scratching.

My current project has exposed me to Service Management Automation, which leads to having to deal with the ins and outs of PowerShell workflows. I thought I’d might as well start publishing some of my learnings, as these might be relevant to you if you’re working with Workflows natively or by using SMA or Azure Automation.

PowerShell workflows can call other PowerShell orkflows. This is even encouraged, in order to obtain some level of code reuse.

If you’ve worked with PowerShell workflows you already know that it’s a bit of an odd bird compared to “regular” PowerShell. Commands can be run “natively” in the PowerShell, or you can use “InlineScript” to call stuff that for some reason doesn’t work natively. InlineScript comes with its own set of hazards though, so the rule of thumb is to do as much as possible natively (with some exceptions, of course).

The thing I wanted to show in this post, is that workflows are a bit picky when it comes to parameter naming. As you know, when calling cmdlets and functions “natively” in Workflows, you have to use named parameters (as opposed to positional parameters) and you also have to use the actual cmdlet/function name, aliases don’t work.

In order to call a “child workflow” from a “parent workflow” in your editor you would simply dot-source your child workflow (or hit F5 if you have it open in the editor) and it will be imported and ready to use by your parent workflow.

Here’s an example: rb-sub is the child workflow, and rb-intermediate is my “parent” (those are some funky names, I know):

workflow rb-sub
{
    Param ([int]$Id)
    Write-Verbose "rb-sub: ID is $id"

    $NewNumber = $Id*2
    $NewNumber
}

workflow rb-intermediate
{
    Param([int]$id)
    Write-verbose "rb-intermediate: id is $id"

    $newnumber = rb-sub -id $id
    Write-verbose "rb-intermediate: newnumber is $newnumber"
}

It’s a fairly simple example. The parent workflow takes an int argument, passes it to the child, which multiplies it by two and sends it back up to the parent.

The point of all this, is that the parent workflow as it sits right now won’t work. And it baffled me for the longest time. Here’s the error you’ll get if you try to run it:

Could not find a parameter named ‘id’. Supported parameters are: Debug, ErrorAction, Input, MergeErrorToOutput, PSActio
nRetryCount, PSActionRetryIntervalSec, PSActionRunningTimeoutSec, PSAllowRedirection, PSApplicationName, PSAuthenticati
on, PSCertificateThumbprint, PSComputerName, PSConfigurationName, PSConnectionRetryCount, PSConnectionRetryIntervalSec,
 PSConnectionUri, PSCredential, PSDebug, PSDisableSerialization, PSError, PSPersist, PSPort, PSProgress, PSProgressMess
age, PSRemotingBehavior, PSRequiredModules, PSSessionOption, PSUseSsl, PSVerbose, PSWarning, Result, Verbose, WarningAc
tion.
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : CouldNotFindParameterName

It translates down to: you’ve tried to pass an argument which doesnt exist. Which is of course hogwash. If you use intellisense/autotype in the ISE, you’ll see that the editor actually suggests the “id” parameter all by itself.

So, whats wrong? It turns out that when you do parent/child workflows like this, they can’t share a parameter name(!). So, before you give up and start typing inlinescript try to change the parameter name of the child workflow like such:

workflow rb-sub
{
    Param ([int]$SomeId)
    $Id = $SomeId
    Write-Verbose "rb-sub: ID is $id"

    $NewNumber = $Id*2
    $NewNumber
}

workflow rb-intermediate
{
    Param([int]$id)
    Write-verbose "rb-intermediate: id is $id"

    $newnumber = rb-sub -Someid $id
    Write-verbose "rb-intermediate: newnumber is $newnumber"
}

This time, I simply changed the parameter name of the child runbook to “someid”. Since I’m lazy I just continued to use the “id” as the actual internal parameter inside the workflow.

This time, your workflow will execute without problems and you can go home to lunch.

Just as a side note; Calling child workflows inside of SMA and Azure Automation doesn’t require any dot-sourcing. Any runbook is available for you to run from any other runbook. As long as you keep watching those parameter names.


Viewing all articles
Browse latest Browse all 9

Trending Articles