You may come into work one day and find that your workflows are failing. Examining the workflow details will reveal "Failed On Start" errors. Most likely this is due to a patch. The fix for the patch is to manually add several lines to the web.config file of your SharePoint web application servers. In my case, I was replacing our SharePoint 2010 servers that were running Windows Server 2008 R2 with servers running Windows Server 2012 R2. All patches were applied before the server was added to the SharePoint farm. As such, the relevant web.config modifications were not in the web.config file. The end result was the same, workflows failing to start on the new 2012 R2 front end servers.
Workflow Foundation (WF) will only run workflows when all the dependent types and assemblies are authorized in the .NET config file (or added explicitly via code) under this tree:
<configuration> <System.Workflow.ComponentModel.WorkflowCompiler> <authorizedTypes> <authorizedType Assembly="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" NameSpace="System.CodeDom" TypeName="CodeBinaryOperatorExpression" Authorized="True" /> <authorizedType Assembly="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" NameSpace="System.CodeDom" TypeName="CodePrimitiveExpression" Authorized="True" /> <authorizedType Assembly="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" NameSpace="System.CodeDom" TypeName="CodeMethodInvokeExpression" Authorized="True" /> <authorizedType Assembly="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" NameSpace="System.CodeDom" TypeName="CodeMethodReferenceExpression" Authorized="True" /> <authorizedType Assembly="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" NameSpace="System.CodeDom" TypeName="CodeFieldReferenceExpression" Authorized="True" /> <authorizedType Assembly="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" NameSpace="System.CodeDom" TypeName="CodeThisReferenceExpression" Authorized="True" /> <authorizedType Assembly="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" NameSpace="System.CodeDom" TypeName="CodePropertyReferenceExpression" Authorized="True" />
The above authorized types are the lines necessary to make SharePoint 2007 and 2010 start running workflows correctly again. They should be applied to every SharePoint farm server that is running the Microsoft SharePoint Foundation Web Application service.
Once you've fixed your SharePoint farm servers, the next step is to find all the workflows that have failed on start. The following PowerShell script will crawl your entire portal and report back on "Failed On Start" workflows:
# Title: FindFailedOnStartWorkflows.ps1 # Version: 1.0, 22 APR 2020 # Author: James Sanders # Purpose: Find all workflows that failed on start # Add the PowerShell Snap-In Add-PSSnapin Microsoft.SharePoint.PowerShell -EA SilentlyContinue # Set Variables $wfFailedOnStart = 0 $wfDetails = "" $timeStarted = Get-Date # Enumerate portal looking for workflows that have failed on start ForEach ($site in (Get-SPSite -Limit All)) { Write-Host Write-Host "Processing site:" $site.Url ForEach ($web in $site.AllWebs) { Write-Host "Processing web: " $web.Url ForEach ($list in $web.Lists) { If ((!($list.Hidden)) -And $list.WorkflowAssociations.Count -ge 1) { Write-Host "Processing list:" $list.Title ForEach ($item in $list.items) { # Find item workflows that have ran but are not in a "Completed" state $BadWorkflows = $item.workflows | Where {$_.InternalStatus -ne "Completed"} If ($BadWorkflows) { # Enumerate problematic workflows ForEach ($BadWorkflow in $BadWorkflows) { # Only looking for "Failed On Start" workflows, which is determined by Status1 field = 1 If ($BadWorkflow.xml -match "Status1=""1""") { $wfa = $list.WorkflowAssociations | Where {$_.ID -eq $BadWorkflow.AssociationID} # Make sure there is not a newer run of the workflow that completed If ($item[$wfa.Name] -ne 5) { Write-Host $Badworkflow.ParentItem.ID $wfa.Name "Failed On Start" $wfStatus = "<a href='$($web.URL)/_layouts/Workflow.aspx?ID=$($BadWorkflow.ParentItem.ID)&List={$($list.ID)}'>Status</a>" $wfDetails += "$($site.RootWeb.Title),$($web.Title),$($list.Title),$($Badworkflow.ParentItem.ID),$($wfa.Name),$wfStatus|" $wfFailedOnStart++ } } } } } } } $web.Dispose() } $site.Dispose() } # Finalize script statistics $timeFinished = Get-Date $timeDuration = ("{0:hh\:mm\:ss}" -f ($timeFinished - $timeStarted)).Substring(0,12) # Display statistics Write-Host Write-Host "Failed On Start Workflows: $wfFailedOnStart" Write-Host Write-Host "Script started: $timeStarted" Write-Host "Script finished: $timeFinished" Write-Host "Duration: $timeDuration" $mailMsgServer = "<YOUR_MAIL_SERVER>" $mailMsgSubject = "Failed On Start Workflows" $mailMsgFrom = "<[email protected]>" $mailMsgTo = "<[email protected]>" $mailMsgBody = "" $mailMsgBody += "<style>" $mailMsgBody += ".TR1 {border: 0px; padding: 0px; border-collapse: collapse;}" $mailMsgBody += ".TD1 {border: 0px; padding: 0px;}" $mailMsgBody += ".TH2 {border: 1px solid gray; padding: 0px; border-collapse: collapse; background-color: #80ffff;}" $mailMsgBody += ".TR2 {border: 1px solid gray; padding: 0px; border-collapse: collapse;}" $mailMsgBody += ".TD2 {border: 1px solid gray; padding: 2px; border-collapse: collapse;}" $mailMsgBody += "</style>" $mailMsgBody += "<table>" $mailMsgBody += "<tr class='TR1'><td class='TD1'>Failed On Start Workflows:</td><td class='TD1'>$wfFailedOnStart</td></tr>" $mailMsgBody += "<tr class='TR1'><td class='TD1' colspan='2'> <br/></td></tr>" $mailMsgBody += "<tr class='TR1'><td class='TD1'>Script started:</td><td class='TD1'>$timeStarted</td></tr>" $mailMsgBody += "<tr class='TR1'><td class='TD1'>Script finished:</td><td class='TD1'>$timeFinished</td></tr>" $mailMsgBody += "<tr class='TR1'><td class='TD1'>Duration:</td><td class='TD1'>$timeDuration</td></tr>" $mailMsgBody += "</table><br/>" If ($wfDetails.Length -gt 0) { $mailMsgBody += "<table>" $mailMsgBody += "<tr class='TH2'><td class='TD2'>Site Collection</td><td class='TD2'>Web Site</td><td class='TD2'>List</td><td class='TD2'>ID</td><td class='TD2'>Workflow</td><td class='TD2'>Status</td></tr>" $wfDetailsLines = $wfDetails.Split("|") ForEach ($line in $wfDetailsLines) { If ($line.Length -gt 0) { $mailMsgBody += "<tr class='TR2'>" $wfDetailsItems = $line.Split(",") ForEach ($item in $wfDetailsItems) { $mailMsgBody += "<td class='TD2'>$item</td>" } } $mailMsgBody += "</tr>" } } $mailMsgBody += "</table><br/>" Send-MailMessage -From $mailMsgFrom -to $MailMsgTo -subject $mailMsgSubject -Body $mailMsgBody -SmtpServer $mailMsgServer -BodyAsHTML
Modify the following lines to fit your organization:
$mailMsgServer = "<YOUR_MAIL_SERVER>" $mailMsgSubject = "Failed On Start Workflows" $mailMsgFrom = "<[email protected]>" $mailMsgTo = "<[email protected]>"