PortiBlog

Updating SharePoint Designer workflows on many sites through PowerShell

13 november 2017

At a customer we found an error in a workflow after we already provisioned thousands of site collections using a Office dev PnP site template. The error results in adding a minor version to a document, when the workflow executed. The workflow updated the Status field inside the properties of the document, which results in an extra minor version.This was caused by the following setting in SharePoint Designer 2013: “Automatically update the workflow status to the current stage name”. With thanks to the following article: SharePoint 2013 Designer Workflow and lists with versioning Workflow settings - AutosetStageName

However updating this setting in SharePoint Designer is not an option if you already have thousands of sitecollections provisioned with the incorrect workflow. The only option to correct this is with Powershell.

After some research how to handle workflows in powershell in combination of SharePoint Online, i found the following article: How to publish a Workflow Definition in SharePoint using PowerShell This article shows how to create a new simple workflow based on a XAML definition in SharePoint Online. As part of this script I found the need of the referenced assembly:  "Microsoft.SharePoint.Client.WorkflowServices.dll" , this is part of SharePoint PnP Core CSOM core assemblies and can be extracted from NuGet site, follow this link: SharePoint PnP Packages to extract the required assemblies for SharePoint Pnp Core. I rewrote the function to get the already existing workflow definition:


$siteurl = "[siteurl]" 

[System.Reflection.Assembly]::LoadFrom("Microsoft.SharePoint.Client.WorkflowServices.dll") 

Connect-PnpOnline $siteurl
$web = Get-PnpWeb
$site = Get-PnpSite
$ctx = $web.Context
$ctx.Load($web)
$ctx.Load($site)
$ctx.ExecuteQuery()

$wfm = New-Object Microsoft.SharePoint.Client.WorkflowServices.WorkflowServicesManager -ArgumentList $ctx,$web

# Get a reference to the Workflow Deployment Service
$wfDeploymentService = $wfm.GetWorkflowDeploymentService()

# Load the incorrect Workflow from it's definition
$wfDefinition1 = Get-PnPWorkflowDefinition -Name "Request Contract Review"
$wfDefinition = $wfDeploymentService.GetDefinition($wfDefinition1.Id) 
$ctx.Load($wfDefinition)
$ctx.ExecuteQuery()

After executing the script above we can modify any setting of the $wfDefinition inside the SharePoint Online site. To change the setting “Automatically update the workflow status to the current stage name” I found a property of the workflow  definition called "AutosetStatusToStageName". But this is not updating the workflow so no new minor versions are created, this only seems to be a cosmetic property. But when I update this checkbox inside SharePoint Designer, then no new minor versions are created. Because I can check all properties before and after the change in SharePoint Designer using the powershell code above, I can compare these two settings. I found that changing the checkbox, also triggers changes in the XAML definition of the workflow. It changes


<local:SetWorkflowStatus Disabled="False" Status="Check status"/>

into


<local:SetWorkflowStatus Disabled="True" Status="Check status"/>

In other words it disables the SetWorkflowStatus action(s) inside the XAML definition. Please note you can have multiple SetWorkflowStatus action(s), one per workflow stage. Check the script below to see how these properties can be modified inside of the workflow definition.


$wfDefinition.Xaml = $wfDefinition.Xaml.Replace('SetWorkflowStatus Disabled="False"','SetWorkflowStatus Disabled="True"')

$wfDefinition.SetProperty("AutosetStatusToStageName","false")

# Save and publish the Workflow Definition object
$definitionId = $wfDeploymentService.SaveDefinition($wfDefinition)
$ctx.Load($wfDefinition)
$ctx.ExecuteQuery()

# Publish the Workflow Definition
$wfDeploymentService.PublishDefinition($definitionId.Value)

The powershell code above are used to change the behaviour of the workflow to not create any minor versions anymore. There are more properties which can be set inside a workflow definition: WorkflowDefinition properties.

After changing the workflow definition, you can also set the workflow subscription, which is the link between the workflow and the library. You could change the start options of the workflow:


$targetLibrary = $web.Lists.GetByTitle("Sales")
$ctx.Load($targetLibrary)
$ctx.ExecuteQuery()

#Get the existing workflow subscription 
$wfSubscriptionService = $wfm.GetWorkflowSubscriptionService()
$subs =Get-PnPWorkflowSubscription

# Configure the Workflow Subscription
$subs.DefinitionId = $definitionId.Value
$subs.Name = $wfDefinition.DisplayName
$subs.Enabled = $true


# Available values are: ItemAdded, ItemUpdated, WorkflowStart
$eventTypes = New-Object System.Collections.Generic.List[String]
$eventTypes.Add("WorkflowStart") 
$eventTypes.Add("ItemAdded") 
$eventTypes.Add("ItemUpdated") 
$subs.EventTypes = $eventTypes

# Publish the Workflow Subscription
$wfSubscriptionService.PublishSubscriptionForList($subs, $targetLibrary.Id)
$ctx.ExecuteQuery()

To recap if you ever need to change an already existing workflow, you can use above scripts to fix your problem. You can also make an update in the xaml definition of an existing workflow. Follow these steps:

1. Get the workflow definition/ subscription using powershell and store all properties and xaml.


$wfDefinition.Properties| fl *
$subs.PropertyDefinitions | fl *

2. Make your changes using SharePoint Designer to create a correctly working workflow

3. Check the properties again, using the powershell code of step 1

4. Make a powershell script using all of the above powershell code blocks to create an updated workflow definition and/or subscription.

5. Have fun!

 

Submit a comment