Showing posts with label workflow. Show all posts
Showing posts with label workflow. Show all posts

2011-07-24

How to Get Workflow History Programmatically

I introduced how to check workflow status in the last post.
Today, I introduce how to get workflow history from Workflow History List. You can find Workflow History List's URL by using SharePoint Designer.



Workflow History List is here. There are some columns associated with workflow.



The code is here. The code enables to get all workflow status associated each item in SharePoint site. You can modify the code to get a specific list's workflow status. I identify workflow history list item using "Workflow History Parent Instance" column and "Primary Item ID" column.(see "if" block.)

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;

// This is Console Application //

SPSite site = new SPSite("http://sharepoint-site");
SPWeb web = site.OpenWeb();

foreach (SPList list in web.Lists)
{
    foreach(SPListItem item in list.Items)
    {
        foreach (SPWorkflow workflow in item.Workflows)
        {
            foreach (SPListItem worflowHistoryItem in workflow.HistoryList.Items)
            {
                if (("{" + workflow.InstanceId.ToString() + "}" == worflowHistoryItem["Workflow History Parent Instance"].ToString()) 
                    && (item.ID.ToString() == worflowHistoryItem["Primary Item ID"].ToString()))
                {
                    Console.WriteLine(item.Name + " : " + worflowHistoryItem["Description"]);
                }
            }
        }
    }
}

2011-06-26

How to Check Workflow Status programmatically

Today I'll show checking all workflow statuses in SharePoint site programmatically. Sometimes you may want to check workflow statuses are error or not.

You need workflow status name (list column) when you get a item's workflow status. But you can't get workflow status name from SPWorkflow properties directly. You need to use SPWorkflow.AssociationId property and SPList.WorkflowAssociations property to get workflow status.


The sample code is here.

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;

// This is Console Application //

SPSite site = new SPSite("http://sharepoint-site");
SPWeb web = site.OpenWeb();

foreach (SPList list in web.Lists)
{
    foreach (SPListItem item in list.Items)
    {
        foreach (SPWorkflow workflow in item.Workflows)
        {
            try
            {
                Console.WriteLine("item url : " + item.Url);
                Console.WriteLine("workflow name : " + list.WorkflowAssociations[workflow.AssociationId].Name);
                Console.WriteLine("workflow status : " + item[list.WorkflowAssociations[workflow.AssociationId].Name]);
                Console.WriteLine();
            }
            catch (ArgumentException)
            {
                //ArgumentException is throwed if the workflow is not exist in the list column. 
                Console.WriteLine("Workflow name : {0} is already not exist in List title : {1}.", 
                    list.WorkflowAssociations[workflow.AssociationId].Name, list.Title);
            }
        }
    }
}

The result is like this :
item url : Lists/Announcement01/1_.000
workflow name : Approval01
workflow status : 2
Workflow status is displayed as a number. The workflow status number are related to SPWorkflowStatus Enumeration. For example, number 2 means "InProgress".

2011-06-11

How to Customize Default Approval Workflow (Part.2)

In Part. 1 blog post, I introduced how to add Person or Group TextBox as CC form in Change Request Task Form. Only adding CC form, It doesn't work. So, in this blog post, I introduce how to add logic in custom Approval workflow to use CC form.



The Steps are here.

  • In Approval - Copy05 Top, click "Edit Workflow" and click "Approval Workflow Task (en-US) Copy".


  • Click "Change the behavior of a single task".


  • Add "Set Workflow Variable" in "When a Task Completes" section's top.


  • Click "workflow variable" and click "Create a new variable..." from pulldown. Fill in arbitrary name and choose String Type. Press OK.


  • Click value and click fx. Fill bellow parameters.


  • Click "Current Task:Assigned To" in "When a Task is Pending".


  • Click icon besides CC. Select "Workflow Lookup for a User...". And Fill in bellow parameters.


  • Click OK and publish the workflow.

The steps were finished. Please confirm that you can get CC email when you run the workflow.

Tips:
In the steps, I created a workflow variable in "When a Task Completes" section to get CC form content. And I added the workflow variable as a CC address in "When a Task is Pending" section. The important point is that you can't directly get CC form content in "When a Task is Pending" section. When you fill in CC form and click Send in Change Request form of a workflow task, The workflow task is completed and new workflow task is created. CC form content is associated the completed task. So you need to get CC form content in "When a Task Completes" section.

2011-06-02

How to Customize Default Approval Workflow (Part.1)

I'm sorry it has been taken long time since previous blog post.
Today I'd like to introduce how to customize default approval workflow using only SharePoint Designer (with non code).
This is new feature in SharePoint 2010. In SharePoint 2007, we couldn't customize default approval workflow. So you needed to make new own workflow from zero base if you want to customize approval workflow.


I introduce these steps in two blog posts.



OK, I introduce Part1 first, add bellow Person or Group TextBox as CC in ChangeRequest in Task Form.




The Steps are here.

  • First create a copy of default Approval Workflow in SPD. Click Copy and Modify and create new copy of default Approval Workflow.


  • Click Approval Workflow Task.

  • Click New in Task Form Fields to create CC as Person or Group Field.


  • Fill in these TextBox, choose Person or Group in Information type, and click Next.



  • Click Finish.


  • Save and Publish the .Approval Workflow.
  • Back to Approval - Copy05 page. Click Approval Workflow Task in Form.


  • Task Form is opened in InfoPath 2010. Check the CC form which was created previous step. 

  • Select CC Row and copy it(Control + C). Delete CC Row from default form.

Tips : You can also add CC from Fields property menu. But you can't resolve names in CC by using Enter key if you drag & drop CC from Fields property menu to ChangeRequest form. So you had better use the copy from default form.

  • Click Page Design Tab and choose ChangeRequest from View pulldown.

  • Add new Row and paste CC Row (Control + V) in ChangeRequest form.


  • Save the InfoPath form to local and Publish it.


Steps were finished.
I'll introduce how to use the CC in next blog post.


2011-04-09

troubleshooting in making workflow each steps (InvalidOperationException and ArgumentNullException)

This time, I introduce how to make simple workflow and its troubleshooting.
Someone who makes workflow encounter a few exceptions. I show each resolutions when workflow execution.


  • Make Sequential Workflow from SharePoint 2010 template.


  • Make simple workflow. CreateTask, Delay, and CompleteTask.

  • Set correlation Token same as onWorkflowActivated1 for createTask1 and completeTask1 in each properties menu.
onWorkflowActivated1 : workflowToken
createTask1              : workflowToken
completeTask1           : workflowToken
  • Build, deploy and run in particular list. Of course, It doesn't work. 


I checked ULSlog and found bellow InvalidOperationException about workflow.

System.InvalidOperationException:
Correlation value on declaration "workflowToken" is already initialized.  
at System.Workflow.Runtime.CorrelationToken.Initialize(Activity activity, ICollection`1 propertyValues)  
at System.Workflow.Activities.CorrelationService.InvalidateCorrelationToken(Activity activity, Type interfaceType, String methodName, Object[] messageArgs)  
at System.Workflow.Activities.CallExternalMethodActivity.Execute(ActivityExecutionContext executionContext)     at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext)  
at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext)  
at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime)  
at System.Workflow.Runtime.Scheduler.Run()

This error is little bit tricky.
What we need to do is using new correlation token for each set of createTask and completeTask.
onWorkflowActivated1 : workflowToken
createTask1              : TaskToken1
completeTask1           : TaskToken1


We use orrelation token to identify each tasks. If you have two tasks in workflow, you can set here.

onWorkflowActivated1 : workflowToken
createTask1              : TaskToken1
completeTask1           : TaskToken1
createTask2              : TaskToken2
completeTask2           : TaskToken2

  • Let's build, deploy and run again !  But,, you still get ArgumentNullException...
System.Reflection.TargetInvocationException:
Exception has been thrown by the target of an invocation. ---> System.ArgumentNullException: Value cannot be null.  
at Microsoft.SharePoint.Workflow.SPWorkflow.GetReservedItemId(SPList list, Guid taskId, Boolean createNew)  
at Microsoft.SharePoint.Workflow.SPWorkflow.GetReservedItemId(SPList list, Guid taskId)  
at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTaskWithContentTypeInternal(Guid taskId, SPWorkflowTaskProperties properties, Boolean useDefaultContentType, SPContentTypeId ctid, HybridDictionary specialPermissions)  
 at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTask(Guid taskId, SPWorkflowTaskProperties properties, HybridDictionary specialPermissions)  
--- End of inner exception stack trace ---  
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)  
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)  
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)  
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)     at System.Workflow.Activities.CallExternalMethodActivity.Execute(ActivityExecutionContext executionContext)  
at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext)  
at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext)  
at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime)  
at System.Workflow.Runtime.Scheduler.Run()

It seems that this error occurs when createTask execute.
In here, What we need to do is setting new GUID for createTask.

  • Double-click "TaskId" in createTask1 properties. and make new Field which bind TaskId.


You can find bellow code is generated.

public Guid createTask1_TaskId1 = default(System.Guid);



  • Double-click "TaskProperties" in createTask1 properties. and make new Field which bind TaskProperties.


You can find bellow code is generated.

public SPWorkflowTaskProperties createTask1_TaskProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();


  • Double click onWorkflowActivated1 and write code in onWorkflowActivated1_Invoked like this.

private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
{
    this.workflowId = workflowProperties.WorkflowId;
}

  • Double click createTask1 and write code in createTask1_MethodInvoking like this.

private void createTask1_MethodInvoking(object sender, EventArgs e)
{
    this.createTask1_TaskId1 = Guid.NewGuid();
    this.createTask1_TaskProperties1.Title = "Please approve the document.";
    this.createTask1_TaskProperties1.AssignedTo = "domain\\someone";
}



  • Let's build, deploy and run again !
done.... It's heavy work.



So, this time is spring. We can see a lot of cherry blossoms. enjoy now !!