views:

350

answers:

2

I am trying out Workflow 4.0 and hoping to write a custom activity to start an external executable, wait for that process to complete and then resume subsequent steps in the workflow.

I found the following example that shows (towards the bottom of the page) how to write an activity to waiting for a file to arrive in a specific directory:

Creating Custom Activities with Workflow 4.0

I have a couple of problems with the example. Firstly, when I add the following code:

void FileCreated(object sender, FileSystemEventArgs e)
{
    instance.ResumeBookmark(bookmarkName, e.FullPath);
    fsw.Dispose();
}

instance.Resumebookmark(...) does not seem to be available but instance.BeginResumeBookmark and instance.EndResumeBookmark are.

I am also unsure of how to change this around to deal with external processes, rather than just watching the contents of a directory.

Is this even the best approach for this kind of thing?

+1  A: 

This approach works perfectly well for running other processes. Use the Process.WaitForExit to check when the process is done, optionally checking the ExitCode, and resume the bookmark.

Maurice
+1  A: 

I would suggest writing an AyncCodeActivity and avoid bookmarks altogether. Here is an example of a custom activity that returns the process exit code as the result:

    public sealed class RunProcess : AsyncCodeActivity<int>
    {
        public InArgument<string> FileName { get; set; }
        public InArgument<string> Arguments { get; set; }

        private Func<string, string, int> runProcessAsyncCall;

        protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
        {
            this.runProcessAsyncCall = this.RunProcessImpl;
            return runProcessAsyncCall.BeginInvoke(FileName.Get(context), Arguments.Get(context), callback, state);
        }

        protected override int EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
        {
            return this.runProcessAsyncCall.EndInvoke(result);
        }

        private int RunProcessImpl(string fileName, string arguments)
        {
            Process p = Process.Start(fileName, arguments);
            p.WaitForExit();
            return p.ExitCode;
        }
    }

In general, bookmarks are great if the external event will not come for a potentially long time. If the process you're invoking is short-lived, an AsyncCodeActivity might be a better choice (it's certainly an easier one to manage).

Chris Gillum