If you are experiencing this problem, first thing you need to check
is this great post.
If your workflow is not in Visual Studio, rather it's a SPD
workflow, what you can do is create a Timer Job which runs every couple of minutes and set the workflow version. Here is the Code:
// Feature receiver
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Administration;
using **.Code.TimerJobs;
namespace **.Features.Unlock_Workflow_Tasks
{
[Guid("***")]
public class Unlock_Workflow_Tasks : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
if (webApp == null)
return;
try
{
// make sure the job isn't already registered
foreach (SPJobDefinition job in webApp.JobDefinitions)
{
if (job.Name == JOB_NAME)
job.Delete();
}
}
catch
{
}
// install the job
UnlockWorkflowTasks timerJobDefinition = new UnlockWorkflowTasks(JOB_NAME, webApp);
SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.Interval = 15;
schedule.BeginSecond = 0;
schedule.EndSecond = 59;
timerJobDefinition .Schedule = schedule;
timerJobDefinition .Update();
}
// Uncomment the method below to handle the event raised before a feature is deactivated.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
// delete the job
try
{
foreach (SPJobDefinition job in webApp.JobDefinitions)
{
if (job.Name == JOB_NAME)
job.Delete();
}
}
catch
{
}
}
}
}
// The Timer Job
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;
using **.Code.Utilities;
using Microsoft.SharePoint.Workflow;
namespace **.Code.TimerJobs
{
class UnlockWorkflowTasks : SPJobDefinition
{
public UnlockWorkflowTasks(): base() {}
public UnlockWorkflowTasks(string jobName, SPWebApplication webApplication)
: base(jobName, webApplication, null, SPJobLockType.Job)
{
this.Title = "**";
}
public override void Execute(Guid contentDbId)
{
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(WebApplication.Sites[0].Url))
using (SPWeb web = site.OpenWeb())
{
UnlockPotentiallyLockedWorkflowTasks(web);
}
});
}
catch (Exception ex)
{
Logger.LogError(ex);
}
}
private void UnlockPotentiallyLockedWorkflowTasks(SPWeb web)
{
try
{
web.AllowUnsafeUpdates = true;
SPListItemCollection tasks = GetPotentiallyLockedTasks(web);
foreach (SPListItem task in tasks)
{
try
{
if ((int)task[SPBuiltInFieldId.WorkflowVersion] != 1)
{
// change it's version to 1.0
SPList parentList = task.ParentList.ParentWeb.Lists[new Guid(task[SPBuiltInFieldId.WorkflowListId].ToString())];
SPListItem parentItem = parentList.Items.GetItemById((int)task[SPBuiltInFieldId.WorkflowItemId]);
SPWorkflow workflow = parentItem.Workflows[new Guid(task[SPBuiltInFieldId.WorkflowInstanceID].ToString())];
if (!workflow.IsLocked)
{
task[SPBuiltInFieldId.WorkflowVersion] = 1;
task.SystemUpdate();
Logger.LogInfo("Unlock task {0} (ID:{1})", task["Title"].ToString(), task["ID"].ToString());
}
}
}
catch (Exception e)
{
Logger.LogError(e);
}
}
}
catch (Exception e)
{
Logger.LogError(e);
}
finally
{
web.AllowUnsafeUpdates = false;
}
}
private SPListItemCollection GetPotentiallyLockedTasks(SPWeb web)
{
var query = new SPQuery();
query.Query = @"
<Where>
<Neq>
<FieldRef Name='Status' />
<Value Type='Choice'>Completed</Value>
</Neq>
</Where>";
//query.ViewAttributes = "Scope=\"Recursive\"";
return web.Lists[WORKFLOW_TASKS_LIST].GetItems(query);
}
}
}
No comments:
Post a Comment