Click here to Skip to main content
Click here to Skip to main content

Hello WWF using C++/CLI

, 27 Jan 2007 CPOL
Rate this:
Please Sign up or sign in to vote.
How to build a Hello World WWF application using C++/CLI

Introduction

Windows Workflow Foundation represents one of the Key technologies in the .NET framework version 3.0(Formerly known as WinFX). There are lot of samples in WWF using languages such as C#, VB.NET etc. Being a C++ fan, I tried to build a sample using C++/CLI. There is no support for building applications in C++/CLI using Visual Studio Extensions for WWF.Project types appear only under Visual C#. So for building the application you have to do almost everything by hand. These are the important points to remember when developing WWF applications under C++/CLI.

  • Lack of Project types to quickly build a template
  • No support for debugging XOML etc.
  • Lack of Design time support for workflow authoring.

If you are willing to live up with these things you can do development of WWF applications under C++/CLI. There could be some scenarios where it might be beneficial to do Development in C++/CLI. You have some existing code base in C++ which you would like to workflow enable. You can create a C++/CLI Activity Library and plug it into the Workflow runtime. Inside the Activity library you can use the IJW feature of C++/CLI to call your native code. Secondly C++/CLI might emit faster optimized IL code which you could consider for even a Workflow hosting environment. Pre-requisites for starting workflow development in WWF are .NET 3.0 framework Windows Workflow Foundation Runtime Components Visual Studio 2005 Extensions for WWF. Let us discuss some key concepts of developing workflow applications before we delve into code.

What is WWF?

WWF can be thought of consisting of tools,engine and a model for building workflow applications. It is not a end user product, it is more of a software developer tool. This infact is the core difference between BizTalk Server and WWF. Biztalk is a server product while WWF is a runtime which developers need to leverage on. There are many industry accepted standards behind workflow frameworks. WFMC is one such standard(www.wfmc.org). BPEL is another. Windows workflow foundation model is a standard which you have to live upto if you are serious about workflow development under WWF. In WWF, a workflow definition consists of Activities. There are two main types of workflows in WWF.

  • Sequential Workflows used for well-defined, business processes
  • State Machine used for human workflows

Workflows can be long running. Support for this comes in the form of persistance service etc. Many aspects of the Runtime can be customized by developing our own custom services. For e.g if you don't like the persistance service and you would like to write the state to a Access mdb, then you can write a custom Persistance Service and plug it into the Workflow runtime.

Once you have decided on the type of workflow for a scenario, the next point is developing activities which constitute the workflow. There are out of the box activities and you can develop custom activities. Activities can be single or composite. A composite activity itself comprises of individual activities. A workflow can be thought of as a composite activity. This allows you to call a workflow within a workflow. This could happen if you want to call a Financial process within a Leave workflow.

A real benefit of developing Workflows to model processes in your buisnesses is simplifying complex looking scenarios by visually modelling them and therby providing the ability to extend them.By making it declarative and expliict, a Workflow definition creates the correct abstraction for the scenario.

Constructing a Sequential Workflow

Let us construct a simple workflow consisting of just two activities. Thw workflow model was constructed with the C# Sequential Workflow Console application project type. In WWF, you can create workflows either using markup or imperatively using any CLR language. The markup specification is similar to XAML in WPF, and for the Designer to distinguish that it is in fact a Workflow definition rather than a graphics application the extension is XOML. Studying the project and understanding how the workflow runtime was invoked helped me to construct a project using C++/CLI. If you construct a Sequential Workflow console application project in C#. There are two main classes generated. One is the workflow class which is derived from SequentialWorkflowActivity. When you drag and drop CodeActivities from the toolbox member variables are created in this class of type CodeActivity. Secondly the events of Actvities are hooked so that when the runtime is used to start the workflow and activities are triggered, the sink functions are invoked. The second aspect is the Shell which invokes the workflow runtime and creates an instance of the workflow which we constructed using markup. The shell also starts the workflow instance thus created. Create a C++/CLI console application called WorkflowApp.CPP. You would be provided with a main function as expected. The first part is constructing the Workflow class.

//The workflow 
ref class Workflow1: SequentialWorkflowActivity
{
public:    
    Workflow1()
    {
        codeActivity1 = gcnew CodeActivity();
        codeActivity2 = gcnew CodeActivity();
        
        this->Activities->Add(codeActivity1);
        this->Activities->Add(codeActivity2);

        codeActivity1->ExecuteCode += gcnew EventHandler(
            this, &Workflow1::codeActivity1_ExecuteCode);
        codeActivity2->ExecuteCode += gcnew EventHandler(
            this, &Workflow1::codeActivity2_ExecuteCode);
    }
private:
    void codeActivity1_ExecuteCode(System::Object^ sender, 
                                   EventArgs^ e)
    {
        Console::Write("Hello");

    }
        
    void codeActivity2_ExecuteCode(System::Object^ sender, 
                                   EventArgs^ e)
    {
        Console::WriteLine("World");
    }

    CodeActivity^ codeActivity1;
    CodeActivity^ codeActivity2;

};
The code is self explanatory. The workflow class consists of two activities of type CodeActivity. In the ctor we create them and hook the ExecuteCode event onto sink functions. The workflow class is derived from SequentialWorkflowActivity. Now comes the main function.
int main(array<System::String ^> ^args)
{

    //Hosting the runtime 
    try
    {
        //create an instance of workflow runtime    
        WorkflowRuntime^ wf = gcnew WorkflowRuntime();
        //using that create an instance of Workflow1
        WorkflowInstance^ workflowInstance =  wf->
            CreateWorkflow(Workflow1::typeid);
        //Start the workflow
        workflowInstance->Start();  
        
        //wait for the workflow to execute
        Console::ReadLine();
    }

    catch(WorkflowValidationFailedException^ ex)
    {
        String^ str = ex->Message;
        Console::WriteLine(str);
    }

    return 0;
}

The next step would be to create an instance of the workflow and start it. For this we have to create an instance of the Workflow runtime first. You need to create the runtime instance only once during the application lifetime. Next we use the CreateWorkflow function of the workflow runtime to create an instance of our workflow. The CreateWorkflow function is heavily overloaded.You can create it from a type , you can create it from a XML markup which is in the XAML format etc. Here we use the typeid operator to get the type associated with the workflow that we have defined.

When you run this, the workflow is started and each activity is executed one by one and you get the expected output. Notice the use of Console::ReadLine towards the end which results is a wait so that the workflow can finish execution. A more serious implementation would be to use a Event object and using one of the wait functions.

System::Threading::AutoResetEvent^ waitHandle = 
    gcnew System::Threading::AutoResetEvent(false); 
...

workflowInstance->Start();
waitHandle->WaitOne();

Developing a Custom Activity

Next we will see how to develop a Custom activity. For this, all you have to do is to write a class derived from Activity and override the Execute virtual fuction. The code is simple and straightforward.

ref class CustomActivity : System::Workflow::ComponentModel
    ::Activity
{
protected:
    virtual ActivityExecutionStatus Execute(
       ActivityExecutionContext^ executionContext) override  
    {
        Console::WriteLine("Custom activity executed");
        return ActivityExecutionStatus::Closed;
    }
};

Notice the return type.It is of type ActivityExecutionStatus . If everything is as expected we return ActivityExecutionStatus::Closed. But if for some reason we want to stop the workflow we can provide a return status ActivityExecutionStatus::Canceling to stop the workflow from further execution.

In order to plug in the custom activity all you have to do is to add it into the workflow class. You need not hook the event sink.

codeActivity3 = gcnew CustomActivity();
this->Activities->Add(codeActivity3);

Conclusion

As you can observe developing in C++/CLI is a little difficult as you lack support from the IDE and template code generators. However if you understand how the pieces fit togther you can develop workflow applications in any CLR compliant language.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Renjith mohan
Web Developer
India India
No Biography provided

Comments and Discussions

 
JokeWF PinmemberBjornar11-Aug-07 13:30 
GeneralRe: WF PinmemberMattman20614-May-08 15:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141015.1 | Last Updated 27 Jan 2007
Article Copyright 2007 by Renjith mohan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid