Debug Workflow Logging using a Custom LogToHistoryListActivity
I don't know about anyone else, but a very valuable resource to me when debugging a MOSS workflow is to put LogToHistoryListActivity instances throughout my workflow so that I can easily see what is going on. I use this technique a lot when developing MOSS workflows, especially long-running workflows where it's really not feasible to sit there with the debugger attached for long periods of time.
With all of these LogToHistoryListActivity instances in my workflow, I find it a pain to either go through and remove them (and any associated member variables and Invoking methods) or to set all of their Enabled properties to false (which I prefer as it means you can get the debug information back by simply setting the Enabled property back to true again, rather than having to re-implement your debugging code !)
To help me with debugging, I've developed a simple custom activity called DebugLogToHistoryListActivity which only logs to the history list if the workflow is built in a Debug configuration. If the workflow is built using a Release configuration the workflow executes as if the DebugLogToHistoryListActivity instances weren't present. Now, instead of adding LogToHistoryListActivity instances in my workflow for debugging purposes I add DebugLogToHistoryListActivity instances instead.
OK, so how do we develop this simple custom activity (and it really is simple as you'll see in a minute) ?
1. Add a new Activity to your workflow project called DebugLogToHistoryListActivity.cs.
2. Right-click on the new file in Solution Explorer and select "View Code" to show the code that has been generated for this activity by default. The code should look like that shown below:
public partial class DebugLogToHistoryListActivity: SequenceActivity
{
public DebugLogToHistoryListActivity()
{
InitializeComponent();
}
}
3. As you can see, when you create a custom activity by default it inherits from the SequenceActivity class. Modify this so that it inherits from Microsoft.SharePoint.WorkflowActions.LogToHistoryListActivity instead by ensuring that the project has a reference to the Microsoft.SharePoint.WorkflowActions DLL and adding a "using Microsoft.SharePoint.WorkflowActions;" declaration in your code file.
4. Override the Execute method of the base class, and enter the following code:
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
{
#if DEBUG
return base.Execute(context);
#else
return ActivityExecutionStatus.Closed;
#endif
}
Basically, the above code performs the base class implementation if the build is a Debug build, otherwise it simply indicates that the processing of the activity has completed by returning ActivityExecutionStatus.Closed.
5. Once this has been built you can add instances of this activity to your workflow and use them in exactly the same was as you would use an instance of a LogToHistoryListActivity. The only difference is that these will only execure in a Debug build. When you build your workflow in Release configuration it will execute as if these activities weren't present.
The complete code listing can be seen below. I hope this is of use to some of you.
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint.WorkflowActions;
namespace
{
public partial class DebugLogToHistoryListActivity: LogToHistoryListActivity
{
public DebugLogToHistoryListActivity()
{
InitializeComponent();
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
{
#if DEBUG
return base.Execute(context);
#else
return ActivityExecutionStatus.Closed;
#endif
}
}
}
With all of these LogToHistoryListActivity instances in my workflow, I find it a pain to either go through and remove them (and any associated member variables and Invoking methods) or to set all of their Enabled properties to false (which I prefer as it means you can get the debug information back by simply setting the Enabled property back to true again, rather than having to re-implement your debugging code !)
To help me with debugging, I've developed a simple custom activity called DebugLogToHistoryListActivity which only logs to the history list if the workflow is built in a Debug configuration. If the workflow is built using a Release configuration the workflow executes as if the DebugLogToHistoryListActivity instances weren't present. Now, instead of adding LogToHistoryListActivity instances in my workflow for debugging purposes I add DebugLogToHistoryListActivity instances instead.
OK, so how do we develop this simple custom activity (and it really is simple as you'll see in a minute) ?
1. Add a new Activity to your workflow project called DebugLogToHistoryListActivity.cs.
2. Right-click on the new file in Solution Explorer and select "View Code" to show the code that has been generated for this activity by default. The code should look like that shown below:
public partial class DebugLogToHistoryListActivity: SequenceActivity
{
public DebugLogToHistoryListActivity()
{
InitializeComponent();
}
}
3. As you can see, when you create a custom activity by default it inherits from the SequenceActivity class. Modify this so that it inherits from Microsoft.SharePoint.WorkflowActions.LogToHistoryListActivity instead by ensuring that the project has a reference to the Microsoft.SharePoint.WorkflowActions DLL and adding a "using Microsoft.SharePoint.WorkflowActions;" declaration in your code file.
4. Override the Execute method of the base class, and enter the following code:
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
{
#if DEBUG
return base.Execute(context);
#else
return ActivityExecutionStatus.Closed;
#endif
}
Basically, the above code performs the base class implementation if the build is a Debug build, otherwise it simply indicates that the processing of the activity has completed by returning ActivityExecutionStatus.Closed.
5. Once this has been built you can add instances of this activity to your workflow and use them in exactly the same was as you would use an instance of a LogToHistoryListActivity. The only difference is that these will only execure in a Debug build. When you build your workflow in Release configuration it will execute as if these activities weren't present.
The complete code listing can be seen below. I hope this is of use to some of you.
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint.WorkflowActions;
namespace
{
public partial class DebugLogToHistoryListActivity: LogToHistoryListActivity
{
public DebugLogToHistoryListActivity()
{
InitializeComponent();
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
{
#if DEBUG
return base.Execute(context);
#else
return ActivityExecutionStatus.Closed;
#endif
}
}
}