Have you ever come across a SharePoint list that has hundreds or thousands of workflows running against it? Terminating those workflows individually using the web interface would possibly be the biggest time suck of your life! Fortunately, there's a script for that. Read on to terminate SharePoint workflows with PowerShell.
The following PowerShell script will terminate a) running workflows, b) workflows in an error occurred state or c) all of the above.
# Title: TerminateWorkflows.ps1 # Version: 2.0, 14 JAN 2022 # Author: James Sanders # Purpose: Programmatically terminate workflows # # Add the PowerShell Snap-In Add-PSSnapin Microsoft.SharePoint.PowerShell -EA SilentlyContinue # Specify the following values # $webURL URL to the web site containing the list to be processed # $listName Name of the SharePoint list # $wfName Name of the workflow to check # $wfState Which workflows to terminate. Specify one of the following workflow states: # "Running" - Terminate running workflows # "Error" - Terminate workflows that are in an error occurred state # "All" - Terminate workflows that are running or in an error occurred state $webURL = "http://porta/site/url" $listName = "Name of SharePoint list" $wfName = "Name of list workflow" $wfState = "All" # Open Web Site $spa = Start-SPAssignment Write-Host Write-Host "- Opening web site $webURL" $web = $spa | Get-SPWeb $webURL -ErrorAction SilentlyContinue If (!($web)) { Write-Host -ForegroundColor Red "- Unable to open web site $webURL" Stop-SPAssignment $spa Exit } # Open SharePoint List Write-Host "- Opening list $listName" $list = $web.lists[$listName] If (!($list)) { Write-Host -ForegroundColor Red "- Unable to open list ""$listName""" Stop-SPAssignment $spa $web.Dispose() Exit } # Enumerate Workflows # 2 = Running # 3 = Error Occured Write-Host "- Looking for running workflows to terminate" $itemsRunning = $list.Items | Where {($_[$wfName] -eq 2)} Write-Host "- Looking for errored workflows to terminate" $itemsErrored = $list.Items | Where {($_[$wfName] -eq 3)} if (!($itemsRunning) -and !($itemsErrored)) { Write-Host "- No workflows to terminate" Stop-SPAssignment $spa $web.Dispose() Exit } # Get site workflow manager $manager = $web.Site.WorkflowManager # Get workflow association $assoc = $list.WorkflowAssociations | where {$_.Name -like $wfName} If (!($assoc)) { Write-Host -ForegroundColor Red "- Workflow ""$wfName"" does not exist" Stop-SPAssignment $spa $manager.Dispose() $web.Dispose() Exit } $data = $assoc.AssociationData # Terminate running workflows If (($wfState -eq "Running") -Or ($wfState -eq "All")) { If ($itemsRunning) { If (!($itemsRunning.Count)) { $itemTotal = 1 } Else { $itemTotal = $itemsRunning.Count } $itemCurrent = 1 Write-Host "- Running workflows to terminate: $($itemTotal)" Write-Host ForEach ($item in $itemsRunning) { ForEach ($wf in $item.Workflows) { If ($wf.ParentAssociation.Name -Match $wfName) { $wfIntState = $wf.InternalState If ($wfIntState -eq 'Running') { Write-Host "- Canceling workflow on item $($itemCurrent) of $($itemTotal) (ID: $($item.ID)) ... " -NoNewline [Microsoft.SharePoint.Workflow.SPWorkflowManager]::CancelWorkflow($wf); Write-Host "Done!" } } } $itemCurrent++ } } Else { Write-Host "- Running workflows to terminate: 0" } } # Terminate errored workflows If (($wfState -eq "Error") -Or ($wfState -eq "All")) { If ($itemsErrored) { If (!($itemsErrored.Count)) { $itemTotal = 1 } Else { $itemTotal = $itemsErrored.Count } $itemCurrent = 1 Write-Host "- Errored workflows to terminate: $($itemTotal)" Write-Host ForEach ($item in $itemsErrored) { ForEach ($wf in $item.Workflows) { If ($wf.ParentAssociation.Name -Match $wfName) { $wfIntState = $wf.InternalState If ($wfIntState -eq 'Running, Faulting, Terminated') { Write-Host "- Canceling workflow on item $($itemCurrent) of $($itemTotal) (ID: $($item.ID)) ... " -NoNewline [Microsoft.SharePoint.Workflow.SPWorkflowManager]::CancelWorkflow($wf); Write-Host "Done!" } } } $itemCurrent++ } } Else { Write-Host "- Errored workflows to terminate: 0" } } # Clean up Stop-SPAssignment $spa $manager.Dispose() $web.Dispose()