Terminate running or suspended Workflows in SharePoint 2013 or 2016 - Fabian Neve

About SharePoint, Javascript, PowerShell, and other technical stuff

Wednesday, October 31, 2018

Terminate running or suspended Workflows in SharePoint 2013 or 2016

There are many options to kill workflows in SharePoint which are built on SharePoint 2010 platform. It is a bit more difficult to terminate those on 2013 platform.

Here is a script that terminates all workflows based on their status. It is also possible to filter for specific items with a CAML query and it iterates trough large lists in batch size (of eg. 2000 items), so you won't run in a timeout or memory issue.

In the script there is a second part that will take care of the 2010 workflows, which is located between comment tags.


Add-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue
$webURL = "https://webapplication/sitecollection/site" #change this to the url of the site
$listName = "Listname" #change this to the corresponding list
$web = Get-SPWeb $webURL
$count = 0
$countTarget = 0
$spQuery = New-Object Microsoft.SharePoint.SPQuery
$spQuery.ViewAttributes = "Scope='Recursive'";
$spQuery.RowLimit = 2000 #terminates the workflows in batches
$caml = "<Where><Eq><FieldRef Name='Fieldname' /><Value Type='Text'>Contenttofilter</Value></Neq></Where>" #this filter will be used to terminate workflows on specific items
$spQuery.Query = $caml
if($web -ne $null) {
$web.AllowUnsafeUpdates = $true;
$list = $web.Lists[$listName]
$wfm = New-object Microsoft.SharePoint.WorkflowServices.WorkflowServicesManager($web)
$sub = $wfm.GetWorkflowSubscriptionService()
$wfs = $sub.EnumerateSubscriptionsByList($list.ID)
$wfis = $wfm.GetWorkflowInstanceService()
do {
$listItems = $list.GetItems($spQuery)
$spQuery.ListItemCollectionPosition = $listItems.ListItemCollectionPosition
foreach($item in $listItems)
{
$countTarget++;
#Write-Host "Working on item $($item.ID)" -ForegroundColor Cyan
#SP2013 WORKFLOWS
$workflowInstances = $wfis.EnumerateInstancesForListItem($list.ID,$item.ID)
foreach($wf in $workflowInstances)
{
if($wf.Status -eq "Suspended") { #status to get and terminate, can also be -ne "Completed" or -eq "Started"
$wfName = $wfs | ?{$_.Id -eq $wf.WorkflowSubscriptionId} | select -ExpandProperty Name
$wfID= $wf.ID
$wfStatus = $wf.Status
$wfListItem = $item.Name
$count++;
$wfis.TerminateWorkflow($wf);
Write-Host "Workflow $($wfName) cancelled for: $wfListItem - $($wf.Status)";
#write-host "Workflow Title: $wfName Status: $wfStatus ListItem: $wfListItem"
}
}
#SP2010 WORKFLOWS
<#
foreach ($workflow in $item.Workflows)
{
$wfName = $workflow.ParentAssociation.Name
$wfStatus = $workflow.InternalState
write-host "Workflow Title: $wfName Status: $wfStatus"
#Disregard Completed Workflows
if($workflow.InternalState -ne "Completed")
{
#Cancel Workflows
#[Microsoft.SharePoint.Workflow.SPWorkflowManager]::CancelWorkflow($workflow);
Write-Host "Workflow $($workflow.Title) cancelled for: " $item.ID;
#$count++;
}
}
#>
}
}
while ($spQuery.ListItemCollectionPosition -ne $null)
$web.AllowUnsafeUpdates = $false;
$web.Dispose();
Write-Host "Processed $countTarget items and found $count workflows"
} else {
Write-Host "Web not configured" -ForegroundColor Red
}




No comments:

Post a Comment