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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# 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() |