PowerShell Workflows And When To Use Them

In this post I’m going to cover PowerShell Workflows and when to use them. PowerShell workflows give you capabilities scripts can’t but they also bring constraints and nuances. You have to think about your requirements to determine if you really need workflows or if you can use a different approach to achieve the same end result with less fuss.

When do you need workflows?

  • Long running tasks and I mean really long running, think closer to hours not minutes.
  • Surviving local reboots (expected and unexpected). You can checkpoint at specific locations in the workflow to resume but more detail later in the post.
  • Persistence. You can serialise the workflow state to disk and resume it later. For instance if there is a manual step in the workflow you can suspend it, perform the manual step and resume it again.
  • Fine grained flow control combining parallel and sequential execution. This one is not that obvious when you look at a workflow script but you can mix and match and nest parallel and sequential activities.
  • Workflows are more robust. The engine creates separate runspaces for activities, if an activity crashed it won’t bring down the whole workflow.

There are probably more but these are the ones I ran into.

When don’t you necessarily need them?

There are situations that look like they need workflows but may not necessarily. Using workflows in these cases won’t be wrong, it will work but it might be overkill.

  • Scaling out. Running a simple task on multiple remote servers in parallel can be achieved using remoting. There might be a point where workflows will scale better but only if you avoid InLineScript activities.
  • Handling reboots. To a certain level DSC can also deal with reboots by configuring ActionAfterReboot and RebootNodeIfNeeded in the LCM config MSDN article.
  • Running tasks in parallel on the same machine. For simple scenarios you can use PowerShell jobs to achieve the same result.

How to survive reboots

Surviving reboots seem to creep into workflow discussion a lot so I’ll have a quick look at it.

The simplest scenario, which is not restricted to workflows by the way, is running a workflow or script that is acting on remote machines. In this case you restart the remote machine using the “Restart-Computer -Wait” command or activity for a workflow. You don’t have to do anything extra since the machine running the workflow or script is not restarting and the script or workflow will continue running after the reboot.

If you want to restart the computer running the workflow you have to do a bit more work. This will only work for workflows not scripts. You still use the Restart-Computer activity which will checkpoint the workflow and suspend it before it restarts the machine. When a workflow is suspended it creates a job of type PSWorkflowJob that will survive the reboot. After the machine comes back from a reboot you have to resume the workflow.  If you call Get-Job after the reboot you will see your workflow as one of the jobs and then you can call Resume-Job to resume the workflow.

wfjob

Then you use the normal job related commands to handle the job and see the output using Receive-Job etc.

If you look at this link reboot scenarios are explained in detail and there is also a section that shows how to automate the resumption of workflows.

To survive unexpected reboots you have to checkpoint your workflow using the Checkpoint-Workflow command at logical points in your workflow. Put some thought into where you place the checkpoints to achieve the correct outcome after a reboot.

Note:  You cannot checkpoint inside an InLineScript activity since it cannot be serialised.

Francois Delport

PowerShell Workflows And Visual Studio

In post post I’m going to cover PowerShell Workflows and Visual Studio. When I saw PowerShell Workflow and how it was using Windows Workflow behind the scenes I wondered how it fitted in with designing workflows in the Visual Studio designer. With C# creating large workflows is easier in the Visual Studio designer instead of coding them, I wanted to see if it was the same for PowerShell and how it worked in the designer.

When you create a workflow script in PowerShell it generates a XAML workflow that is executed by .NET. The commands you use in your script are transformed into PowerShell activities in the XAML workflow. If your code doesn’t have a corresponding PowerShell activity it is wrapped in an InlineScript activity. This is transparent to the user but it can have ramifications. The code in an InlineScript activity is executed in a separate PowerShell instance that is loaded for each activity and stays active for the whole activity, this can be bad for performance when running workflows at scale. Activities in a workflow have lots of plumbing around them and the code in the InlineScript activity will not have that plumbing available. For instance you can’t checkpoint inside your InlineScript activity so you won’t be able to recover to a specific point inside the InlineScript. To illustrate the transformation, look at the script sample below:

PowerShell Workflows And Visual Studio

Here is the equivalent workflow that is generated with Write-Output resulting in a WriteOutput activity and Start-BitsTransfer resulting in an InlineScript activity.

PowerShell Workflows And Visual Studio

I’m not aware of a command in PowerShell that will inform you if your code has a corresponding workflow activity but you can do a visual inspection by exporting your workflow to XAML, opening it in Visual Studio and looking for InlineScript activities or searching the XAML text for InlineScript. Using the same script as above, I wrote the XAML to a file which you can open in Visual Studio.

(get-command Invoke-MyFirstWorkFlow).XamlDefinition |out-file c:\temp\MyFirstWorkFlow.xaml

You can view the activities available by adding them to the toolbox in the workflow designer. As far as I could see most of them are in these assemblies.

  • Microsoft.PowerShell.Activities
  • Microsoft.PowerShell.Core.Activities
  • Microsoft.PowerShell.Diagnostics.Activities
  • Microsoft.PowerShell.Management.Activities
  • Microsoft.PowerShell.Security.Activities
  • Microsoft.PowerShell.Utility.Activities
  • Microsoft.WSMan.Management.Activities

I uploaded the list of PowerShell workflow activities I found in the above assemblies along with their corresponding PowerShell commands over here.

In theory you can design your workflow in Visual Studio, import the XAML file in PowerShell and execute it like the example below.

PowerShell Workflows And Visual Studio

I assume this is not the intended use-case since it didn’t work that well for large workflows, especially if you are not using the PipeLine activity and that limits you to activities that is pipeline enabled. I think part of the problem is all the extra plumbing activities that PowerShell injects to handle expressions and variable values etc which you have to do now as well.

PowerShell can also execute workflows from XAML files by importing the file as a module.

Import-Module "C:\Temp\PowerWorkFlow.xaml"

PowerWorkFlow #name of the workflow

If you are going to distribute and re-use the workflow you should package it like a proper PowerShell module instead of passing the XAML file around.

While going through all of this I started to wonder why you would use PowerShell workflows in the first place since they have a bit of a learning curve and many restrictions. Hopefully I’ll be doing a post on that soon.

Francois Delport