using System; using System.Collections.Generic; using System.Text; using System.Workflow.Runtime.Hosting; using System.Workflow.Runtime; using System.Diagnostics; using System.Collections.Specialized; namespace WFServices { // Define the delegate that will be used when writing output internal delegate void WriterDelegate ( string output ); /// /// This service is designed to output all events raised by the workflow runtime to the Debug log /// public class RuntimeEventWriter : WorkflowRuntimeService { /// /// Construct the object and decide which writer(s) we're going to use /// /// public RuntimeEventWriter(NameValueCollection args) { // Create an empty delegate just in case the user has not supplied any parameters _writers = new WriterDelegate(WriteNowhere); if (args["Console"] == "true") _writers = (WriterDelegate)Delegate.Combine(_writers, new WriterDelegate(WriteToConsole)); if ( args["Trace"] == "true") _writers = (WriterDelegate)Delegate.Combine(_writers, new WriterDelegate(WriteToTrace)); if (args["Debug"] == "true") _writers = (WriterDelegate)Delegate.Combine(_writers, new WriterDelegate(WriteToDebug)); } /// /// Hook all runtime events /// protected override void OnStarted() { Runtime.WorkflowAborted += new EventHandler(OnWorkflowAborted); Runtime.WorkflowCompleted += new EventHandler(OnWorkflowCompleted); Runtime.WorkflowCreated += new EventHandler(OnWorkflowCreated); Runtime.WorkflowIdled += new EventHandler(OnWorkflowIdled); Runtime.WorkflowLoaded += new EventHandler(OnWorkflowLoaded); Runtime.WorkflowPersisted += new EventHandler(OnWorkflowPersisted); Runtime.WorkflowResumed += new EventHandler(OnWorkflowResumed); Runtime.WorkflowStarted += new EventHandler(OnWorkflowStarted); Runtime.WorkflowSuspended += new EventHandler(OnWorkflowSuspended); Runtime.WorkflowTerminated += new EventHandler(OnWorkflowTerminated); Runtime.WorkflowUnloaded += new EventHandler(OnWorkflowUnloaded); } /// /// Unhook all runtime events /// protected override void OnStopped() { Runtime.WorkflowAborted -= new EventHandler(OnWorkflowAborted); Runtime.WorkflowCompleted -= new EventHandler(OnWorkflowCompleted); Runtime.WorkflowCreated -= new EventHandler(OnWorkflowCreated); Runtime.WorkflowIdled -= new EventHandler(OnWorkflowIdled); Runtime.WorkflowLoaded -= new EventHandler(OnWorkflowLoaded); Runtime.WorkflowPersisted += new EventHandler(OnWorkflowPersisted); Runtime.WorkflowResumed -= new EventHandler(OnWorkflowResumed); Runtime.WorkflowStarted -= new EventHandler(OnWorkflowStarted); Runtime.WorkflowSuspended -= new EventHandler(OnWorkflowSuspended); Runtime.WorkflowTerminated -= new EventHandler(OnWorkflowTerminated); Runtime.WorkflowUnloaded -= new EventHandler(OnWorkflowUnloaded); } void OnWorkflowUnloaded(object sender, WorkflowEventArgs e) { _writers.Invoke (string.Format("Workflow {0} Unloaded at {1}.", e.WorkflowInstance.InstanceId, DateTime.Now)); } void OnWorkflowTerminated(object sender, WorkflowTerminatedEventArgs e) { _writers.Invoke (string.Format("Workflow {0} Terminated at {1}.\r\n Exception was '{2}'.\r\n{3}", e.WorkflowInstance.InstanceId, DateTime.Now, e.Exception.Message, e.Exception.StackTrace)); } void OnWorkflowSuspended(object sender, WorkflowSuspendedEventArgs e) { if ( string.IsNullOrEmpty ( e.Error) ) _writers.Invoke(string.Format("Workflow {0} Suspended at {1}.", e.WorkflowInstance.InstanceId, DateTime.Now)); else _writers.Invoke(string.Format("Workflow {0} Suspended with error at {1}.\r\n Error was '{2}'.", e.WorkflowInstance.InstanceId, DateTime.Now, e.Error)); } void OnWorkflowStarted(object sender, WorkflowEventArgs e) { _writers.Invoke(string.Format("Workflow {0} Started at {1}.", e.WorkflowInstance.InstanceId, DateTime.Now)); } void OnWorkflowResumed(object sender, WorkflowEventArgs e) { _writers.Invoke(string.Format("Workflow {0} Resumed at {1}.", e.WorkflowInstance.InstanceId, DateTime.Now)); } void OnWorkflowPersisted(object sender, WorkflowEventArgs e) { _writers.Invoke(string.Format("Workflow {0} Persisted at {1}.", e.WorkflowInstance.InstanceId, DateTime.Now)); } void OnWorkflowLoaded(object sender, WorkflowEventArgs e) { _writers.Invoke(string.Format("Workflow {0} Loaded at {1}.", e.WorkflowInstance.InstanceId, DateTime.Now)); } void OnWorkflowIdled(object sender, WorkflowEventArgs e) { _writers.Invoke(string.Format("Workflow {0} Idled at {1}.", e.WorkflowInstance.InstanceId, DateTime.Now)); } void OnWorkflowCreated(object sender, WorkflowEventArgs e) { _writers.Invoke(string.Format("Workflow {0} Created at {1}.", e.WorkflowInstance.InstanceId, DateTime.Now)); } void OnWorkflowCompleted(object sender, WorkflowCompletedEventArgs e) { StringBuilder sb = new StringBuilder(); foreach (KeyValuePair kvp in e.OutputParameters) { sb.AppendFormat(" {0} = {1}\r\n", kvp.Key, (kvp.Value == null) ? "null" : kvp.Value ); } _writers.Invoke(string.Format("Workflow {0} Completed at {1}.\r\n Output Parameters were...\r\n{2}", e.WorkflowInstance.InstanceId, DateTime.Now, sb.ToString())); } void OnWorkflowAborted(object sender, WorkflowEventArgs e) { Debug.WriteLine(string.Format("Workflow {0} Aborted at {1}.", e.WorkflowInstance.InstanceId, DateTime.Now)); } /// /// Write the text to the console /// /// void WriteToConsole(string text) { Console.WriteLine(text); } /// /// Write the text to the debug stream /// /// void WriteToDebug(string text) { Debug.WriteLine(text); } /// /// Write the text to the trace stream /// /// void WriteToTrace(string text) { Trace.WriteLine(text); } /// /// Don't write the text anywhere /// /// void WriteNowhere(string text) { } /// /// Delegate used to output data to the console/debug/trace /// private WriterDelegate _writers; } }