Hi All,
Is there a way to retrieve a strongly typed reference to the actual running workflow from a WorkflowInstance instance
More details:
I have a runtime event handler (loaded, idled) that receives a WorkflowEventArgs parameter. In that method I would like to access some of the instance properties (DependencyProperties) of my own workflow class. The only object I have in that method is a WorkflowInstance with an InstanceId. So the question is, how can I get a MyWorkflowClass instance if I have an InstanceId
Thanks in advance.

Accessing workflow instance members from WorkflowInstance (runtime event handlers)
Ken98045
I understand and appreciate the reasoning behind tracking+workflow locking+queuing/EDX etc. but it just doesn't feel like it was trialled with anything more than the smallest of WF applications. Tracking is fine for a simple audit trail, but if you want to get the current state of your custom properties in a strongly-typed data structure then you need to spend a lot of time and effort synchronising your custom Activities with your TrackingProfiles, TrackingExtracts, UserTrackingRecords and whatever you use to translate UserTrackingRecords into something more meaningful than a bunch of name/value pairs. Adding a subclassed workflow type or a new activity property requires edits to several classes just to ensure the data is properly tracked and retrieved. Not to mention the poor OOB tracking query support and the lack of utility methods e.g. getting the latest/current tracking record against a given activity. Of course you can implement a custom tracking service to try and overcome all these limitations, but who has time do that for real (& I don't mean the tinker-toy tracking service samples).
P.S. how about an FAQ thread on this forum - this question (along with confusion over the WorkflowDefinition property) is among several that seem to show up here pretty regularly.
BeckyB
I started a previous thread stating the same complaint. This is rediculous design (IMO).
Honestly, I am not saying this to offend - but it is my perception - Stop paying attention to factories and patterns from every gall darn OO book on the market and let's explore this issue (matbe we need a NEW pattern)!!!!
PLEASE !!
Now that I demonstrated my frustration through capital letters, I cannot agree more: why do I have to add another "service" to query the state of an existing instance I understand that anything that the workflow must respond to, should use the eproper interfaces and messaging, but simply having an instance on a service running and wanting to know "what's up with it" should NOT require another service (OMG). let's say we have an instance of a service called:
myService
WHY - PLEASE - WHY
Why, can I not simple get:
myService.CurrentState
Why
This is STUPID!!.. or... am I totally not getting how this could "blow up" workflows
Sorry, again, I am not trying to offend, but it makes no sense (from what little I do know) >>> if there IS a good reason, then, please, POST IT. I have always run off the theory of open discussion including any unnecessary emotional responses and that we should all be prepared that there is a "good" reason. Ya know: to coin a phrase, "throw it up in the air and see if it gets shot"
It seems like many, many users are throwing the same question in the air and the reason/ response we get is "We have the Tracking Service". Okay, SO WHAT!
Please, answer the "actual" question.
What is the reason or reasons that instance properties of a workflow instance do not actually contain state information (anything actually intuitive and useful)
Thank you!
Again, I am not angry, but I am emotional and would like some serious consideration given to this topic because WF is not intuitive (to many users) when a separate service must be created to identify properties of a currently active workflow.
TIA
Trevor
Sai A
sorry I was in a hurry and I didn't read the question as I should.
the traditional way to achieve this is to use the Tracking Service
Jon Limjap
I have a new sample that shows a very simple tracking service to get the current property values of a running workflow instance. The tracking service creates a profile so that as each activity closes, the tracking service gets sent a tracking record containing all of the property values of the workflow. It then stores these in a dictinary, so the host process (i.e. your external code) can query the service for the current properties.
I hope this helps some people out, as I know this is frustrating area for people. In many cases, you should be able to plug this service in and use it without any/many modifications.
Matt
Read more and find the link to the source at: http://pluralsight.com/blogs/matt/archive/2006/11/25/42637.aspx
2000MPH
Hi,
I don't have the sdk/doc/VStudio on my current pc so I cannot test it for the moment, but if that helps (in a hurry) I think you can use the GetWorkflowDefinition() which returns a template of the root Activity which is your workflow; if you get the type of this root activity->...
Serge
AlexBB
Hello Shelly and thanks for the reply. I really do understand messaging and communication, but I believe (or at least hope) that is not the way in my case.
Let me just rephrase the question:
In the runtime event handlers (loaded, idled) is the tracking service the only way to get more information about the workflow instance that was just loaded or idled So there I have a WorkflowInstance instance and I have to use the tracking service to access the properties and the fields of the running workflow
Thank you again.
Gyorgy
n3sachde
Hello Serge,
Thanks for the reply but unfortunately it does not work.
There is a GetWorkflowDefinition() method, but it returns a workflow template and not the actual running instance. The properties of this returned template does not contain the value of my workflow instance. The template could be good to modify the workflow but it is not what I want now.
So the case is still open, does anybody have any ideas
Thanks,
Gyorgy
fjcardoso
Shelly,
what about the Tracking Service
Serge
slsjr
I'm also concerned about lack of access to the workflow instance. I understand why the workflow passivation feature requires that you hide the workflow instance, since it may not exist. However, passivation is not an important feature for my application and I would disable it (via http://blogs.msdn.com/advancedworkflow/archive/2006/05/19/602116.aspx). It's far more important for me to have a reflectable, and invokable instance of the workflow instance.
So my question is, are there reasons beyond passivation that prevent exposure of the workflow instance Could Microsoft, in a future version, provide a back door to the workflow instance if the developer double promises never to activate the passivation feature
Thanks.
71EFBB98-D1FE-4eff-BAC5-F94AC74
merwy
Messaging and tracking are indeed the only ways to access workflow fields and properties.
Shelly Guo
SamuelS
I actually like and enjoy WF and am happy to learn how to use it, but I am still not agreeing that 'read-only' properties could be provided without requiring the devloper to manually create a separate service. Frankly, the current messaging or communication model does not have to discarded to accomplish this.
Please, consider:
Is it possible for methods behind "read-only" properties of a workflow instance to instantiate the tracking service and retrive what it needs without the developer having to manually create all of the tracking dependant code I believe a good portion of the tracking service should be involked "behind-the-scenes" so that the model is intuitive and "user-friendly" and makes it "seem" that the properties are available as part of the workflow instance.
I understand the need for separation of functionality as far as the "engine" goes, but complete isolation is not the way to go - IMO. This, to me, is like a grid control where there may be several "views" available and only one is currently selected to display the the "current" grid. A well designed grid would be "user-friendly" and expose a property or method to get the current row of the current view. A poor design (IMO) requires the user (developer) of the grid to determine which view is active, get that view, and then get the current row.
I think the scenario I described with the grid has similarities to workflow instances and tracking services From my view, the tracking service is like the view for the grid and a poor design (IMO) makes a user get/ create the service, and retreive the tracking info for the current workflow instance manually. A great/ fantastic design (IMO) would simply do that "stuff" behind-the-scenes because the advantages are tremendous for the end-user. It seems to me that the model would not be broken and data would not be corrupted, but WF would then take into account (greatly) user-interaction, which, ultimately determines to ease-of-use and overall success of a product. Couldn't we eat our cake and have it too
When I design applications, the end-user never cares how its accomplished (under-the-hood); they care how user-friendly the end-result is and that it does perform everything required. Many applications do everything required and then some but they fail miserably in "user-friendly' interaction and therein lies their demise. What happens or how it happens under-the-hood is simply less important than the perception of what happens from the end-user's perspective.
What I believe the problem is ... no wait... that's not correct... it would be better phrased as... I believe there is an "opportunity" for WF and it relates to why I referred to "patterns" in my previous post. Developers often get locked into the patterns that drive the model efficiently and many developers are often satisified when the model performs all the required - core - elements, but (and very very importantly) they often forget, overlook, or simply don't address that many of the patterns need to be decorated with functionality that masks some of the isolation of resposibility such as having the workflow instance utilize some of the tracking internally so that the the model is as 'user-friendly' as possible.
Did I make any sense
TIA
Trevor
Batikit
Sorry you are frustrated. I believe the reason you cannot get those items directly is that it is important that the host not directly interact with the workflow instance and that the workflow instance not directly interact with certain runtime services. This is all driven by the way the threading and scheduling model of workflow behaves. It is important for the workflow to be able to persist (go out of memory) and have its threads managed by the scheduler. If the workflow has to be accessible to the host directly, this becomes more difficult. Since the scheduler is managing the workflow instance, having the host try to access the instance and possibly make changes to it or interact with it, adds all sorts of complexity to you the host writer on dealing with threading, synchronization etc.
I realize this seems like a simple problem from the surface, but the goal is to make WF more accessible. Hopefully, now that there is an answer to how to deal with this, it will be less frustrating for people.
Note that I do not work for Microsoft and these are my opinions. There may be other very good reasons why they chose this design.
Matt
shunt
No, you can not access the running workflow directly from the host. This is explicitly forbidden in order to pretect the integraty of the workflow state. Allowing the host to modify the property values in a workflow may result in inconsistency of the workflow state.
The only way you can talk to a workflow is through messaging. You can do this using ExternalDataExchangeService. Use a HandleExternalEvent to receive the query. If you pass in an object reference, you can use that to return the result. Or you can use a seperate CallExternalMethod to return the result. Return a copy of the property value instead of a reference because the activity classes are not thread safe.
You can also implement a custom root activity that creates a WorkflowQueue to listen to any query message. The queue is created when the root activity is initialized and destroyed when the root is closed. The root activity itself subscribes to the QueueItemAvaialble event. That's how I would do it (see code below).
protected override void Initialize(IServiceProvider provider){
base.Initialize(provider); if (this.Parent == null || this.IsDynamicActivity){
// setup the queue for command queries. WorkflowQueuingService queueService = provider.GetService(typeof(WorkflowQueuingService)) as WorkflowQueuingService; WorkflowQueue queue = queueService.CreateWorkflowQueue(this.Name, true);queue.QueueItemAvailable +=
new EventHandler<QueueEventArgs>(OnQueueEvent);}
protected
override void OnClosed(IServiceProvider provider){
// delete the command query queue WorkflowQueuingService queueService = provider.GetService(typeof(WorkflowQueuingService)) as WorkflowQueuingService; WorkflowQueue queue = queueService.GetWorkflowQueue(this.Name);queue.QueueItemAvailable -=
new EventHandler<QueueEventArgs>(OnQueueEvent);queueService.DeleteWorkflowQueue(
this.Name); base.OnClosed(provider);}