Getting to Workflow Information

Hi, I'm Phil Allen, a developer with the SharePoint Designer team who works primarily on Workflow. Today I'd like to describe how you can get some important data about your workflow as usable data within a workflow action.

This is all about creating new workflow actions, and so, Visual Studio 2005 with the Extension for Windows WF installed will be very helpful. Boot Visual Studio, File -> New -> Project, Other Languages -> Visual C# -> Workflow, Workflow Activity Library is the place to start. Much of the early portions of this article is similar to the blog post on creating new actions for SPD, but is intended to show you how to get to some of the information about the workflow itself as part of the workflow.

It also builds on top of this MSDN magazine article:
https://msdn.microsoft.com/msdnmag/issues/06/12/windowsworkflow/

Suppose for a moment that you wanted to write an action that calculated the time since the workflow started and returns the number of minutes as a string. Create the shell of your activity, giving it the namespace and class name you want it to have. From there, you'll need to start by thinking about the Execute method of your activity:

namespace MyNamespace

{

    public class MyActivity : Activity

    {

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

        {

            //More goes here later

            return ActivityExecutionStatus.Closed;

        }

    }

}

First, you need the current time:

DateTime currentDateTime = System.DateTime.UtcNow;

Notice the use of UtcNow instead of Now; Now is done in the timezone of the local machine, and not the timezone of the website that you are working with.

Second, you need the time the workflow was started. This is a bit trickier, but what you need to get access to is the SPWorkflowActiviationProperties for the current workflow. Every workflow receives one of these as part of OnWorkflowActivated; however, the goal is to make this work seamlessly in SharePoint Designer.

SharePoint Designer's workflow authoring capabilities has a few special names for properties that will automatically be set to certain values that should always be available in the workflow. Specifically, there's a table of the property names, which value they bind to, and the .Net type of that property.

Property Name

Value it is set to

.Net type

__ActivationProperties

__initProps, the SPWorkflowActivationProperties that was passed in via OnWorkflowActivated

Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties

__ListId

__list, the name of the SPList the workflow is executing on. This is typically a string datatype which contains the text of a System.Guid.

System.String

__ListItem

__item, the integer value of the list item in the list that the workflow is running on.

System.Int32

__Context

__context, the object that contains many helper methods and objects for use as part of workflow actions

Microsoft.SharePoint.WorkflowActions.WorkflowContext

In this case, browsing some of the MSDN pages and most importantly their properties, we find that SPWorkflowActivationProperties has a Workflow property of type SPWorkflow, which has Created property which is a DateTime representing the time the workflow started.

To get access to the SPWorkflowActivationProperties in your Execute method, you need to create a property that SharePoint Designer will automatically set to __initProps.

public static DependencyProperty __ActivationPropertiesProperty = DependencyProperty.Register("__ActivationProperties", typeof(Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties), typeof(MyActivity));

 

[ValidationOption(ValidationOption.Required)]

public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties __ActivationProperties

{

    get

    {

        return (Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties)base.GetValue(__ActivationPropertiesProperty);

    }

    set

    {

        base.SetValue(__ActivationPropertiesProperty, value);

    }

}

SharePoint Designer won't automatically do the hookup yet; you'll need to add a little bit to your actions file in order to do so. I'll come back to that later.

At this point, you have access to an object that will give you the SPWorkflowObject you want. You also need to have an output parameter of type System.Int32 to output your number of minutes to. Code for that will look like this:

public static DependencyProperty NumberOfMinutesProperty = DependencyProperty.Register("NumberOfMinutes", typeof(System.Int32), typeof(MyActivity));

 

[ValidationOption(ValidationOption.Required)]

public System.Int32 NumberOfMinutes

{

    get

    {

        return (System.Int32)base.GetValue(NumberOfMinutesProperty);

    }

    set

    {

        base.SetValue(NumberOfMinutesProperty, value);

    }

}

This is your output variable.

The last piece of the activity is to finish writing the Execute method:

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

{

    DateTime currentDateTime = System.DateTime.UtcNow;

//Set this to a recognizable value that would never be a valid value for the started time.

    DateTime startedDateTime = System.DateTime.MinValue;

//Set this to a recognizable value that would never be the result of the real calculation.

    NumberOfMinutes = System.Int32.MaxValue;