In this
article we can explore a real world scenario where a workflow is sending
reminder email to users and the interesting thing is that the task list &
data no long exists.
I have
encountered such scenarios multiple times in my consulting arena and I would
recommend running the latest cumulative updates to resolve the issue. In cases
where the update patching is not feasible you can use the following solution
approach.
Understanding the Problem
To make sure
the problem is being conveyed correctly I am using the following points:
- Task List named Approval List was
created
- A
new item was added to the Task List
- An
Approver is being notified on the task
- The
Task List was deleted, removed from Recycle Bin too
- The
notification mail is being sent every week
- The
user cannot modify the task or approve it to stop the emails
This case
can arise due to an incomplete migration where the relational columns are
mismatched. Our focus is to fix the problem so that our user is not being disturbed
by obsolete or invalid emails.
Examining the Problem
As the first
step you can try to impersonate as the user into the SharePoint web
application. If you cannot access the user credentials you can try examining
the SharePoint content database. The content database contains the list, list
records, user, work flow information for a SharePoint web application.
You can get
the content database name of the web application from Central Administration.
You can see
the content database name from the appearing page. Ensure that you are
referring to the right web application.
You can
click on the Database Name link to see more information about like Server Name.
Now you can
try logging in to the database using SQL Server Management. Following are our
tables of interest. (Here we are examining List Workflows)
Table | Description |
AllLists | This table contains the list metadata
like Title, Description etc. |
AllUserData | This table contains the user data like
list item. |
Workflow | This table contains the workflow
instances. |
Please note that there are no referential constraints but
GUID values are used to interconnect between tables. Following are the table
structures:
Note: Modification to the table using SQL / Direct
Editing is restricted by Microsoft. You should use the Server Object Model for
any modifications.
Proposed Solution
The
advisable solution is to terminate the workflow using the SharePoint user
interface.
To achieve
this open Lists > Site Workflows link.
Click on the
highlighted link as shown above. You should get the following Workflow Information
page.
Click on the
Terminate this workflow now link as shown above.
If the
workflow gets terminated then you are good. Your customer should be happy as
he will be free from the wrong email alert.
You can
verify the database record to ensure the InternalStatus column is set to
8.
The
enumeration for Internal State column mapping to SPWorkflowState is
given below:
Extended Proposed Solution
This
solution involves much more effort and advisable if the User or Administrator
is not able to perform the above. You can write a piece of code to fetch the
workflows under running state and cancel it using the Server Object Model.
Step 1: Create a new windows application
Create a new
windows application and make the .Net version to 3.5, Platform Target to Any
CPU. Add 1 TextBox, 2 Button and 1 ListBox as shown below:
Step 2: List the Workflow Instances
On the Find
Running Workflow button click event invoke the following method which list all
the Workflow Instances.
private void RefreshList()
{
using (SPSite site = new SPSite(UrlText.Text))
{
using (SPWeb web = site.OpenWeb())
{
List.Items.Clear();
_internalList = new List<SPWorkflow>();
foreach (SPWorkflow workflow in web.Workflows)
{
List.Items.Add(workflow.AuthorUser.LoginName +
" " + workflow.InternalState.ToString() +
" " + workflow.Created.ToShortDateString() +
" " + workflow.StatusUrl);
_internalList.Add(workflow);
}
}
}
}
Step 3: Terminate the Workflow
For
terminating the Workflow use the following code.
private void TerminateButton_Click(object sender, EventArgs e)
{
if (List.SelectedIndex >= 0)
{
if (MessageBox.Show("Are you sure to Terminate this Workflow?",
"Confirm", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
{
SPWorkflow workflow = _internalList[List.SelectedIndex];
SPWorkflowManager.CancelWorkflow(workflow);
RefreshList();
MessageBox.Show("Terminated.. The list will be refreshed after Timer Job removes the workflow entry!");
}
}
}
Note: Here we are using SPWorkflowManager
class to terminate the workflow. The CancelWorkflow()
is the method used to
perform the same. After cancelling the item will be removed by a timer job.
Step 4: Execute the Application
On executing
the application you can see all the workflows listed. Selecting the
appropriate workflow and clicking the Terminate button should make the Workflow
Internal State to Cancelled. From this point onwards the obsolete email
problem will be stopped.
Note: Currently the workflow author, date
and url information are added in the list. You are free to add additional
information about the workflow in the list.
References
http://tinyurl.com/sp2010-wf-terminate
Summary
In this
article we have explored a possible problem associated with obsolete task
emails workflow and the solutions for it.
I would like
to iterate that Microsoft recommended way of solution is to use the Server Object
Model or Client Object Model to make the database changes rather than using SQL
statements directly on the content database.
The source
code for the article is attached.