Cancel previous version workflows in a list and restart new ones using Powershell
Problem
You have multiple running workflows in a list either in ‘pause’ or ‘wait for item change’. You make a modification to the workflow and publish again. All existing running workflows become ‘workflow name (previous version: date – time). The next time someone updates the list item, you end up with 2 running workflows. This can be problematic if the workflows are used for notification. For example, the user ends up with 2 notification e-mails.
Solution
You need to find a way to safely cancel all existing workflows and start the new ones. Note, I have checks / conditions in my workflows so that all the restarted workflows pause / wait at the same state as before. This may not be the case for you, so it is best to run this script in a test environment first.
This script will:
- Look for a particular list in a site/subsite.
- Go through all items in the list
- Go through all workflows in each item
- Cancel workflows with names matching ‘wftocancel’.
- Go through the same list
- Look for all items with the field ‘Verified’ = ‘Completed’.
- Start the workflow with name matching ‘wftostart’.
Here is the script, update the lines in bold as required.
If you found this helpful, please like my post. Thank you!
#Site and List
$web = Get-SPWeb http://sitename;
$site = Get-SPSite "http://sitecollection"
$listToCancel = "Listname";
$web.AllowUnsafeUpdates = $true;
#Workflows to Remove
$WfToCancel = "Workflow name (previous version...)";
$wfToStart= "Workflow name"
#List Name
$list = $web.Lists[$listToCancel];
#Workflow Manager
$manager=$site.WorkFlowManager
$association=$list.WorkFlowAssociations | where {$_.Name -eq $wfToStart}
# Iterate through all Items in List and all Workflows on Items.
foreach ($item in $list.Items) {
foreach ($wf in $item.Workflows) {
#Test for workflow complete and match criteria
if (($wf.ParentAssociation.Name -eq $wfToCancel) -and ($wf.IsCompleted -ne $true)) {
#Show status and cancel Workflows
write-Host $wf.ItemName -nonewline;
write-host " " -nonewline;
write-host $wf.ParentAssociation.InternalName;
Write-Host " Status " -nonewline;
Write-host $wf.InternalState;
[Microsoft.SharePoint.Workflow.SPWorkflowManager]::CancelWorkflow($wf);
}
}
}
#Filtered List
foreach ($item in $list.Items) {
if ($item["Verified"] -ne "Completed") {
$data=$association.AssociationData
$wf=$manager.StartWorkFlow($item,$association,$data)
Write-Host "$wftoStart started on " $item.Name
}
else {
Write-Host $item.Name " - no action taken"
}
}
$web.Dispose();
Thank you Andrew. Your scripts saved my evening!