Question

I have a documents list on sharepoint 2013 associated with a simpel sharepoint designer workflow. I am able to start the workflow on the list items from a timerjob using csom code. But when trying to do this using ssom code the workWorkflowAssociations property of the defined list is always empty(Count =0). I have tried many trucs like running the code with RunWithelevatedPrivileges, and adding the service account running the timerjob service to the farm administrators, but it did not help.

                    SPWorkflowManager wfManager = oWeb.Site.WorkflowManager;


                    foreach (SPListItem item in list.Items)
                    {
                        foreach (SPWorkflowAssociation association in list.WorkflowAssociations)
                        {
                            string fieldName = association.Name;
                            SPFieldWorkflowStatus statusField =
                                          list.Fields.GetField(fieldName) as SPFieldWorkflowStatus;

                            // Get the value of the WorkflowStatus field.
                            object value = item[fieldName];

                            //run all workflows associated with the list
                            //initiation parameters    
                            var inputParameters = new Dictionary<string, object>();
                            //inputParameters.Add("MyProperty", "MyValue");
                            wfManager.StartWorkflow(item, association, null);
                        }

                    }

while when querying the same list with the next csom code i get the right workflow association and i am able to start it:

var clientContext = new SP.ClientContext("Myusite");
            var listGuid = new Guid("6F6B063F-5115-4568-BE7D-955E48E801E4");
            var list = clientContext.Web.Lists.GetById(listGuid);

            var workflowServiceManager = new WorkflowServicesManager(clientContext, clientContext.Web);
            var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService();

            //get all workflows associated with the list
            var subscriptionsByList = workflowSubscriptionService.EnumerateSubscriptionsByList(listGuid);
            clientContext.Load(subscriptionsByList);
            clientContext.ExecuteQuery();

            CamlQuery query = new CamlQuery();
           ....
            var items = list.GetItems(query);
            clientContext.Load(items);
            clientContext.ExecuteQuery();
            foreach (var item in items)
            {
                //run all workflows associated with the list
                foreach (var workflowSubscription in subscriptionsByList)
                {
                    //initiation parameters    
                    var inputParameters = new Dictionary<string, object>();
                    //inputParameters.Add("MyProperty", "MyValue");
                    workflowServiceManager.GetWorkflowInstanceService().StartWorkflowOnListItem(workflowSubscription, item.Id, inputParameters);
                    clientContext.ExecuteQuery();
                }
            }
Was it helpful?

Solution

in the first one your using the list to get the workflow association but in the second example your using WorkflowServicesManager that you then pass through the ListID guid through to retrieve the connection.

use in the first example:

var subscriptionsByList = wfManager.EnumerateSubscriptionsByList(listGuid); and then loop through result foreach (var association in subscriptionsByList )

you need to reference Microsoft.SharePoint.WorkflowServicesBase.dll to use EnumerateSubscriptionsByList found here

https://msdn.microsoft.com/library/Microsoft.SharePoint.WorkflowServices.WorkflowSubscription.aspx

OTHER TIPS

To add to Ali Jafer's answer (I cannot comment there due to low reputation):

If you cannot find Microsoft.SharePoint.WorkflowServicesBase.dll, you can download and install it to your project using NuGet:

Install-Package Microsoft.SharePoint.WorkflowServicesBase

Once you have this, you can use it in your code:

public override void Execute(Guid targetInstanceId) 
{
   try
        {
            using (SPSite siteCol = new SPSite(siteUrl))
            {
                using (SPWeb web = siteCol.OpenWeb())
                {
                    SPList calList = web.Lists[listName];
                    if (calList == null) throw new NullReferenceException($"Cannot find list: {listName}");
                    var wfMan = new WorkflowServicesManager(web);
                    var wfInstSvc = wfMan.GetWorkflowInstanceService();
                    var sub = GetSubscriptionByName(workflowName, calList, wfMan);
                    if (sub == null)
                        throw new Exception($"Couldn't find workflow subscription with name: {workflowName}");
                    foreach (SPListItem item in calList.Items)
                    {
                      wfInstSvc.StartWorkflowOnListItem(sub, item.ID, new Dictionary<string,object>());
                    }
                }
            }
        }
        catch(Exception ex)
        {
            //Deal with exception
        }
        //Execute completed.
    }
    private WorkflowSubscription GetSubscriptionByName(string name, SPList list, WorkflowServicesManager wfMan)
    {
        var wfSvc = wfMan.GetWorkflowSubscriptionService();
        var subs = wfSvc.EnumerateSubscriptionsByList(list.ID);
        WorkflowSubscription sub = null;
        foreach (var s in subs)
        {
            if (s.Name == workflowName)
            {
                sub = wfSvc.GetSubscription(s.Id);
                break;
            }
        }


        return sub;
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top