Terminate SharePoint Workflows with PowerShell

By James|01/14/2022|, ,

Introduction

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.

Resolution

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()

 

Copyright 2011 - 2022 The Lazy IT Admin | All Rights Reserved
menu-circlecross-circle linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram