PowerShell – Cancel all Running Workflows

WARNING

DO NOT run this on a production system unless absolutely necessary.  It iterates through all sites, lists, items and workflows.  I have not tested this for performance and system impact.

There have been some requests on how to cancel all running workflows. I’ve looked online and have found a number of C# and PowerShell scripts, but each has resulted in issues of one sort or another.

So I’ve created the script below.  It’s not pretty and probably can be optomized, but it works and I’m happy with it.

What it does, is iterate through site, through each list in the site, each item in the list and then each workflow and if it’s not “Completed” and not “Cancelled”, then it cancels the workflow.

I have found that if you cancel a workflow that is completed or already cancelled, you’ll find a mesasge in the workflow history that the workflow has been cancelled, even though it wasn’t running.  Also, if it’s a Nintex Workflow, you’ll then end up getting an email telling you the workflow was cancelled, when you shouldn’t have even tried to cancel it.

So the below script works for list and site workflows.

Why not use the online scripts?

There are 2 issues I had with scripts I found online.

  1. Scripts were iterating through each web using a ForEach, and that would crash the script since it affects the foreach collection of webs.
  2. Scripts were cancelling workflows that weren’t running.

Improvements that could be made

It’d be nice to turn this into a ps1 file that takes arguments.  So you can pass in the url to the parent site and possibly a listname, item index or workflowname to make this a little smarter.  But for now, this works and you can modify it as you see fit.

Below is the PowerShell Script

It’s hardcoded to localhost but you can change it your own site, or a different url.

$site = Get-SPSite “http://localhost”
if($site)
{
  $spWebCollection = $site.AllWebs;
  $i = 0;
  $iWebCount = $spWebCollection.Count;

  do
  {
    Write-Host $i;

    $web = $spWebCollection[$i];
    $spListCollection = $web.Lists;
    $iListCount = $spListCollection.Count;

    $j = 0;
    do
    {
      $list = $spListCollection[$j];
      $spItemCollection = $list.Items;
      $iItemCount = $spItemCollection.Count;
      $k = 0;

      do
      {
        $item = $spItemCollection[$k];
        $spWorkflowCollection = $item.Workflows;
        if($spWorkflowCollection)
        {
          $iWorkflowCount = $spWorkflowCollection.Count;
          $l = 0;
 
          do
          {
            $workflow = $spWorkflowCollection[$l];
            if($workflow)
            {
              if($workflow.InternalState -ne ‘Completed’ -and $workflow.InternalState -ne ‘Cancelled’)
              {
                [Microsoft.SharePoint.Workflow.SPWorkflowManager]::CancelWorkflow($workflow);
              }
            }
            $l++;
          }
          while ($l -lt $iWorkflowCount)
        }
        $k++;
      }
      while ($k -lt $iItemCount)
      $j++;
    }
    while ($j -lt $iListCount)
   
    # Site Workflows
    $spWorkflowCollection = $web.Workflows;
    if($spWorkflowCollection)
    {
      $iWorkflowCount = $spWorkflowCollection.Count;
      $w = 0;

      do
      {
        $workflow = $spWorkflowCollection[$w];
        if($workflow)
        {
          if($workflow.InternalState -ne ‘Completed’ -and $workflow.InternalState -ne ‘Cancelled’)
          {
            [Microsoft.SharePoint.Workflow.SPWorkflowManager]::CancelWorkflow($workflow);
          }
        }
        $w++;
      }
      while ($w -lt $iWorkflowCount)
    }
    $web.Dispose();
    $i++;
  }
  while ($i -lt $iWebCount)

  $site.Dispose()
}

Leave a Reply

Your email address will not be published. Required fields are marked *