Here is some sample code below. Please let me know if this answers it for you. THis is a console sequential workflow application that invokes a workflow using InvokeWorkflowActivity, and then blocks and waits for that workflow to complete, and then it extracts a return value from the invoked workflow
// Program.cs
#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
using System.Workflow.Activities;
#endregion
namespace WorkflowConsoleApplication11
{
class Program
{
static Guid HostWFGuid;
static LocalService ls;
static void Main(string[] args)
{
using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
// LocalServices
ExternalDataExchangeService dataService = new ExternalDataExchangeService();
workflowRuntime.AddService(dataService);
ls = new LocalService();
dataService.AddService(ls);
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
{
// If we are going to spawn only 1 child workflow
// Then we just need to check that the workflow that
// is completing is not our host workflow, like this
//if (e.WorkflowInstance.InstanceId != HostWFGuid)
// Another way is to compare the completing InstanceId
// with the InstanceID from the Workflow that was invoked
if(e.WorkflowInstance.InstanceId == ls.TargetInstanceId)
{
// This is an Invoked Workflow Completing
// Get out the Return value
// Signal the "Host" Wf that it is complete
int nRetVal = Convert.ToInt32(e.OutputParameters["RetVal"]);
ls.WorkComplete(HostWFGuid, nRetVal);
}
else
{
// We are done, so signal
waitHandle.Set();
}
};
workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowConsoleApplication11.Workflow1));
HostWFGuid = instance.InstanceId;
instance.Start();
waitHandle.WaitOne();
}
}
}
}
This is the local services class:
// LocalServices.cs
using System;
using System.Workflow.Activities;
namespace WorkflowConsoleApplication11
{
[Serializable]
public class MyExternalDataEventArgs : ExternalDataEventArgs
{
public MyExternalDataEventArgs(Guid InstanceID, int nRetValue)
: base(InstanceID)
{
this.RetValue = nRetValue;
}
private int m_nRetValue;
public int RetValue
{
get { return m_nRetValue; }
set { m_nRetValue = value; }
}
}
[ExternalDataExchange]
internal interface ILocalService
{
event EventHandler<MyExternalDataEventArgs> InvokedWorkflowComplete;
void SetTargetId(Guid InstanceId);
void WorkComplete(Guid HostWFGuid, int nRetValue);
}
internal class LocalService : ILocalService
{
public event EventHandler<MyExternalDataEventArgs> InvokedWorkflowComplete;
public void WorkComplete(Guid HostWFGuid, int nRetValue)
{
if (InvokedWorkflowComplete != null)
{
InvokedWorkflowComplete(null, new MyExternalDataEventArgs(HostWFGuid, nRetValue));
}
}
public void SetTargetId(Guid InstanceId)
{
TargetInstanceId = InstanceId;
}
public Guid TargetInstanceId;
}
}
Here is the designer.cs and code beside cs for the Host workflow:
// Workflow1.designer.cs
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Reflection;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace WorkflowConsoleApplication11
{
partial class Workflow1
{
#region Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
[System.Diagnostics.De****NonUserCode]
private void InitializeComponent()
{
this.CanModifyActivities = true;
System.Workflow.ComponentModel.ActivityBind activitybind1 = new System.Workflow.ComponentModel.ActivityBind();
System.Workflow.ComponentModel.WorkflowParameterBinding workflowparameterbinding1 = new System.Workflow.ComponentModel.WorkflowParameterBinding();
System.Workflow.ComponentModel.ActivityBind activitybind2 = new System.Workflow.ComponentModel.ActivityBind();
System.Workflow.ComponentModel.WorkflowParameterBinding workflowparameterbinding2 = new System.Workflow.ComponentModel.WorkflowParameterBinding();
this.codeActivity2 = new System.Workflow.Activities.CodeActivity();
this.handleExternalEventActivity1 = new System.Workflow.Activities.HandleExternalEventActivity();
this.callExternalMethodActivity1 = new System.Workflow.Activities.CallExternalMethodActivity();
this.invokeWorkflowActivity1 = new System.Workflow.Activities.InvokeWorkflowActivity();
this.codeActivity1 = new System.Workflow.Activities.CodeActivity();
//
// codeActivity2
//
this.codeActivity2.Name = "codeActivity2";
this.codeActivity2.ExecuteCode += new System.EventHandler(this.codeActivity2_ExecuteCode);
//
// handleExternalEventActivity1
//
this.handleExternalEventActivity1.EventName = "InvokedWorkflowComplete";
this.handleExternalEventActivity1.InterfaceType = typeof(WorkflowConsoleApplication11.ILocalService);
this.handleExternalEventActivity1.Name = "handleExternalEventActivity1";
activitybind1.Name = "Workflow1";
activitybind1.Path = "MyArgs";
workflowparameterbinding1.ParameterName = "e";
workflowparameterbinding1.SetBinding(System.Workflow.ComponentModel.WorkflowParameterBinding.ValueProperty, ((System.Workflow.ComponentModel.ActivityBind)(activitybind1)));
this.handleExternalEventActivity1.ParameterBindings.Add(workflowparameterbinding1);
//
// callExternalMethodActivity1
//
this.callExternalMethodActivity1.InterfaceType = typeof(WorkflowConsoleApplication11.ILocalService);
this.callExternalMethodActivity1.MethodName = "SetTargetId";
this.callExternalMethodActivity1.Name = "callExternalMethodActivity1";
activitybind2.Name = "invokeWorkflowActivity1";
activitybind2.Path = "InstanceId";
workflowparameterbinding2.ParameterName = "InstanceId";
workflowparameterbinding2.SetBinding(System.Workflow.ComponentModel.WorkflowParameterBinding.ValueProperty, ((System.Workflow.ComponentModel.ActivityBind)(activitybind2)));
this.callExternalMethodActivity1.ParameterBindings.Add(workflowparameterbinding2);
//
// invokeWorkflowActivity1
//
this.invokeWorkflowActivity1.Name = "invokeWorkflowActivity1";
this.invokeWorkflowActivity1.TargetWorkflow = typeof(WorkflowConsoleApplication11.SubWorkflow2);
this.invokeWorkflowActivity1.Invoking += new System.EventHandler(this.TargetWfInvoking);
//
// codeActivity1
//
this.codeActivity1.Name = "codeActivity1";
this.codeActivity1.ExecuteCode += new System.EventHandler(this.codeActivity1_ExecuteCode);
//
// Workflow1
//
this.Activities.Add(this.codeActivity1);
this.Activities.Add(this.invokeWorkflowActivity1);
this.Activities.Add(this.callExternalMethodActivity1);
this.Activities.Add(this.handleExternalEventActivity1);
this.Activities.Add(this.codeActivity2);
this.Name = "Workflow1";
this.CanModifyActivities = false;
}
#endregion
private CodeActivity codeActivity1;
private CodeActivity codeActivity2;
private HandleExternalEventActivity handleExternalEventActivity1;
private CallExternalMethodActivity callExternalMethodActivity1;
private InvokeWorkflowActivity invokeWorkflowActivity1;
}
}
// workflow1.cs
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace WorkflowConsoleApplication11
{
public sealed partial class Workflow1: SequentialWorkflowActivity
{
private MyExternalDataEventArgs myArgs;
public MyExternalDataEventArgs MyArgs
{
get { return myArgs; }
set { myArgs = value; }
}
public Workflow1()
{
InitializeComponent();
}
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Host Workflow Executing");
}
private void codeActivity2_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Return Value from Invoked Workflow {0}", MyArgs.RetValue);
}
private void TargetWfInvoking(object sender, EventArgs e)
{
}
}
}
Here is the child workflow designer and code beside:
// Subworkflow2.Designer.cs
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Reflection;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace WorkflowConsoleApplication11
{
partial class SubWorkflow2
{
#region Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
[System.Diagnostics.De****NonUserCode]
private void InitializeComponent()
{
this.CanModifyActivities = true;
this.codeActivity1 = new System.Workflow.Activities.CodeActivity();
//
// codeActivity1
//
this.codeActivity1.Name = "codeActivity1";
this.codeActivity1.ExecuteCode += new System.EventHandler(this.codeActivity1_ExecuteCode);
//
// SubWorkflow2
//
this.Activities.Add(this.codeActivity1);
this.Name = "SubWorkflow2";
this.CanModifyActivities = false;
}
#endregion
private CodeActivity codeActivity1;
}
}
// SubWorkflow2.cs
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace WorkflowConsoleApplication11
{
public sealed partial class SubWorkflow2: SequentialWorkflowActivity
{
private int x;
public int RetVal
{
get { return x;}
set { x = value;}
}
public SubWorkflow2()
{
InitializeComponent();
}
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
x = 10;
Console.WriteLine("Target Workflow Executing");
}
}
}
Steve Danielson [Microsoft]
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at http://www.hide-link.com/