Microsoft SharePoint and .NET Technology Insight

SharePoint, .NET, Office365, Windows Azure, TFS, Project Server and SQL Server Technology Insights


Leave a comment

Invoking SharePoint Workflows manually from a Custom Timer job

I recently had a requirement to create a custom Timer job in SharePoint 2010 to manually invoke a SharePoint Custom Visual Studio developed Workflow associated with a SharePoint list. See the following code snippet for additional details.

public class ListItemWorkflowProcessingJob : SPJobDefinition
{
     enum ProcessingStatus
     {
          NotCompleted,
          Completed
     };

     public ListItemWorkflowProcessingJob()
     {
     }

     public ListItemWorkflowProcessingJob(string jobName, SPWebApplication webApplication, SPServer server, 
     SPJobLockType targetType) : base(jobName, webApplication, server, targetType)
     {
         Title = "List Item Workflow Processing timer job";
     }

     public ListItemWorkflowProcessingJob(string jobName, SPWebApplication webApplication)
     : base(jobName, webApplication, null, SPJobLockType.Job)
     {
         Title = "List Item Workflow Processing timer job";
     }

     public override void Execute(Guid contentDbId)
     {
        SPWebApplication webApplication = this.Parent as SPWebApplication;
        processListItemWorkflows(webApplication);
     }

     public void processListItemWorkflows(SPWebApplication webApplication)
     {
         using (SPSite site = webApplication.Sites["/"])
         {
          #region Action Delegates
          Action<SPListItem> CancelWorkflows = (ListItem) =>
          {
               SPWorkflowCollection workflows = ListItem.Workflows;
               foreach (SPWorkflow workflow in workflows)
               {
                   SPSecurity.RunWithElevatedPrivileges(() 
                           => SPWorkflowManager.CancelWorkflow(workflow));
               }

          };

          Action<SPListItem> StartWorkflow = (ListItem) =>
          {
               // ID value from Workflow elements.xml file
               Guid wfBaseId = new Guid("54a15d07-f2d7-4626-b82d-5a853802ad0e");
               var wfa = (from SPWorkflowAssociation spwfa in 
                          ListItem.ParentList.WorkflowAssociations
                          where spwfa.BaseId == wfBaseId && spwfa.Enabled == true
                          select spwfa).FirstOrDefault();
               site.WorkflowManager.StartWorkflow(ListItem, wfa, wfa.AssociationData, true);
          };


              #endregion Action Delegates

              site.AllowUnsafeUpdates = true;
              SPList MyList = site.RootWeb.Lists["Custom List"];

              var listItems = from SPListItem item in MyList.Items
                              orderby item.Title
                              ascending
                              where (string)item["ProcessingStatus"].ToString()
                               == ProcessingStatus.NotCompleted.ToString()
                              && item["ProcessingStatus"] != null
                              select item;

              foreach (SPListItem ListItem in listItems)  //each item in the list
              {
                 try
                 {
                     CancelWorkflows(ListItem);
                     ListItem.Update();
                     try
                     {
                        StartWorkflow(ListItem);
                     }
                     catch (Exception ex)
                     {
                         throw ex;
                     }

                     ListItem["ProcessingStatus"] = FIAProcessingStatus.Completed;
                     ListItem.Update();

                    //wait for 10 seconds
                     Thread.Sleep(10000);

                  }
                  catch (Exception ex)
                  {
                    throw ex;
                  }
                }

                MyList.Update();
                site.AllowUnsafeUpdates = false;
           }

        }
}

The  above custom timer job cancels any existing workflow instances running on SharePoint ListItems before manually invoking a new workflow instance. The Startworkflow Action<> Delegate invokes a new workflow instance on a SharePoint list item by using the workflow ID GUID value specified inthe workflow solution elements.xml file.

Advertisements