Searching for a way to check if a workflow is running on a list item (useful, for example, in an item event handler), I found some code like this:
public static bool IsWorkflowRunning(SPListItem listItem, Guid workflowId)
{
foreach (SPWorkflow workflow in listItem.Workflows)
{
if (workflow.ParentAssociation.BaseTemplate.Id == workflowId &&
workflow.InternalState == SPWorkflowState.Running)
{
return true;
}
}
return false;
}
What this code does is iterate the workflows list for the item (point to remember: listItem.Workflows contains not only running workflows, but also cancelled or otherwise) and checks the InternalState for the given workflow id. While it might seem ok, as I found out the hard way, it's not. Correct way to check is like so:
public static bool IsWorkflowRunning(SPListItem listItem, Guid workflowId)
{
foreach (SPWorkflow workflow in listItem.Workflows)
{
if (workflow.ParentAssociation.BaseTemplate.Id == workflowId &&
(workflow.InternalState & SPWorkflowState.Running) == SPWorkflowState.Running)
{
return true;
}
}
return false;
}
The somewhat subtle thing to notice is the check: it denotes that the SPWorkflowState is an enum decorated with the [Flags] attribute, which means that the check has to be changed like above.