Tuesday, August 12, 2014

Get the name of a PowerShell script or workflow from within the script or workflow

Some might argue against the wisdom of building self-awareness into our programs, but if it makes my life easier, bring on singularity.

I was half done with a long series of scripts when a new requirement was introduced.  Each of the scripts needed to finish by logging the datetime and the name of the script to a database.  Going back to finished scripts to retrofit new functionality is always annoying and boring, so I was looking to simplify the task.

I wanted to write a short snippet that I could quickly paste into each script without having to customize each one.  So the snippet needed to be able to get the name of the script without being told.  For a normal PowerShell script, that’s easy.  Well, easy if you Google it, because you won’t find it accidentally.

$MyInvocation.MyCommand.Name

If you try that at a PowerShell command prompt, it will correctly come back with nothing, because you aren’t running a script.  When used in the middle of a running script, the script can find out what its own name is.

Unfortunately, I wasn’t working on normal PowerShell scripts.  I was working on PowerShell workflows for SMA (Service Management Automation, Microsoft’s new automation platform).  PowerShell workflows are defined in PowerShell, but they don’t run in PowerShell.  Behind the scenes, PowerShell converts the PowerShell workflows from PowerShell code to XAML and runs them in Windows Workflow.

So I needed a way for a workflow to get its own name.  I looked everywhere and asked various experts, and couldn’t find an answer anywhere.  Until I happened to actually look at the XAML versions of some of my workflows.  (I was bored and curious.)  And there at the bottom of each one was a reference to the name of workflow, and this variable:

$WorkflowCommandName

Well that's too easy.  I wish I had found that before I customized several dozen scripts.  Oh, well.

And of course, if your code is in an inline script within a PowerShell workflow, you prepend Using: to the variable name.

$Using:WorkflowCommandName

Here are all of them in context:

$ScriptName = $MyInvocation.MyCommand.Name

workflow Test-Code
{
$WorkflowName = $WorkflowCommandName
    InlineScript
    {
    $WorkflowName = $Using:WorkflowCommandName
    }
}