2012-07-09 63 views
2

我正在製作一個類似於Visual Workflow Tracking *的工作流設計器。如何獲取WorkflowApplication的上下文?

我想添加一個新的控制調試WF,但ID不知道如何訪問到WF背景

要運行WF我用這個:

WFApplication wfApp = new WorkflowApplication(act, inputs); 

我的想法是,當我recive trace事件,獲取wfApp的上下文,以獲取變量或參數值。

它是posibble?

*您可以donwload VisualStudioTracking代碼來源: Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 然後 :\ WF_WCF_Samples \ WF \應用\ VisualWorkflowTracking *

回答

4

的名字我終於解決了這個問題。

首先,我從xaml獲取工作流的所有參數名稱和變量。

class XamlHelper 
    { 

    private string xaml; 

    public XamlHelper(string xaml) 
    {   
     this.xaml = xaml; 

     DynamicActivity act = GetRuntimeExecutionRoot(this.xaml); 
     ArgumentNames = GetArgumentsNames(act); 

    GetVariables(act); 
    } 

    private void GetVariables(DynamicActivity act) 
    { 
     Variables = new List<string>(); 
     InspectActivity(act); 


    } 

    private void InspectActivity(Activity root) 
    { 


     IEnumerator<Activity> activities = 
      WorkflowInspectionServices.GetActivities(root).GetEnumerator(); 


     while (activities.MoveNext()) 
     { 

      PropertyInfo propVars = activities.Current.GetType().GetProperties().FirstOrDefault(p => p.Name == "Variables" && p.PropertyType == typeof(Collection<Variable>)); 
      if (propVars != null) 
      { 
       try 
       { 
        Collection<Variable> variables = (Collection<Variable>)propVars.GetValue(activities.Current, null); 
        variables.ToList().ForEach(v => 
        { 
         Variables.Add(v.Name); 

        }); 
       } 
       catch 
       { 

       } 
      } 
      InspectActivity(activities.Current); 
     } 
    } 





    public List<string> Variables 
    { 
     get; 
     private set; 
    } 

    public List<string> ArgumentNames 
    { 
     get; 
     private set; 
    } 


    private DynamicActivity GetRuntimeExecutionRoot(string xaml) 
    { 


     Activity root = ActivityXamlServices.Load(new StringReader(xaml)); 


      WorkflowInspectionServices.CacheMetadata(root); 

     return root as DynamicActivity; 

    } 

    private List<string> GetArgumentsNames(DynamicActivity act) 
    { 
     List<string> names = new List<string>(); 
     if (act != null) 
     { 
      act.Properties.Where(p => typeof(Argument).IsAssignableFrom(p.Type)).ToList().ForEach(dp => 
      { 
       names.Add(dp.Name); 
      }); 

     } 

     return names; 
    } 

} 

其次,我創建跟蹤這些參數和變量名

private static WFTrace CreateTrace(List<string> argumentNames, List<string> variablesNames) 
    { 
     WFTrace trace = new WFTrace(); 
     trace.TrackingProfile = new TrackingProfile() 
     { 
      ImplementationVisibility = ImplementationVisibility.All, 
      Name = "CustomTrackingProfile", 
      Queries = 
       { 
        new CustomTrackingQuery() 
        { 
        Name = all, 
        ActivityName = all 
        }, 
        new WorkflowInstanceQuery() 
        { 


         // Limit workflow instance tracking records for started and completed workflow states 
         States = {WorkflowInstanceStates.Started, WorkflowInstanceStates.Completed }, 
        } 
       } 
     }; 

     trace.TrackingProfile.Queries.Add(GetActivityQueryState(argumentNames, variablesNames)); 

     return trace; 
    } 

,然後調用WF和添加traceextension。

亞當這是代碼

private TrackingQuery GetActivityQueryState(List<string> argumentNames, List<string> variablesNames) 
     { 
      ActivityStateQuery query = new ActivityStateQuery() 
      { 
       ActivityName = "*", 
       States = { ActivityStates.Executing, ActivityStates.Closed } 
      }; 
      if (argumentNames != null) 
      { 
       argumentNames.Distinct().ToList().ForEach(arg => 
       { 
        query.Arguments.Add(arg); 
       }); 
      } 
      if (variablesNames != null) 
      { 
       variablesNames.Distinct().ToList().ForEach(v => 
       { 
        query.Variables.Add(v); 
       }); 
      } 
      return query; 
     } 
+0

嗨,你可以發佈你的'GetActivityQueryState'的實現嗎? – Adam 2013-03-18 21:50:42

+0

我正在嘗試做同樣的事情 - 每當我的工作流程恢復時,我需要收集在ROOT中聲明的變量的值 - 但是我沒有收到任何跟蹤回調信息,我需要這些信息。 – Adam 2013-03-18 22:51:04

1

您可以使用Tracking Participants工作流運行時提取variables and arguments

+0

好的,謝謝。但跟蹤參與者僅捕獲當前活動的變量。所以如果我需要檢查wf全局變量的值...我將需要保存所有變量wf,當活動開始時push vars,當活動完成時彈出。 – 2012-07-10 06:04:04

+0

跟蹤參與者可以捕獲範圍內每個變量的值,而不僅僅是觸發事件的活動中定義的值。不要使用'*'通配符,因爲它只跟蹤當前活動變量,而是使用命名變量。 – Maurice 2012-07-10 07:26:54

+0

但我不知道變量名稱,我有一個WorkflowDesigner控件,並且用戶創建了變量,流程,順序等等... – 2012-07-10 08:09:25

0

我嘗試跟蹤變量與此跟蹤參與者

private static VisualTrackingParticipant VisualTracking() 
    { 
     String all = "*"; 
     VisualTrackingParticipant simTracker = new VisualTrackingParticipant() 
     { 
      TrackingProfile = new TrackingProfile() 
      { 
       Name = "CustomTrackingProfile", 
       Queries = 
        { 
         new CustomTrackingQuery() 
         { 
          Name = all, 
          ActivityName = all 
         }, 
         new WorkflowInstanceQuery() 
         { 
          // Limit workflow instance tracking records for started and completed workflow states 
          // States = { WorkflowInstanceStates.Started, WorkflowInstanceStates.Completed }, 
          States={all} 
         }, 
         new ActivityStateQuery() 
         { 
          // Subscribe for track records from all activities for all states 
          ActivityName = all, 
          States = { all }, 

          // Extract workflow variables and arguments as a part of the activity tracking record 
          // VariableName = "*" allows for extraction of all variables in the scope 
          // of the activity 
          Variables = 
          {         
           { all } 
          }, 
          Arguments={ {all}} 
         } 
        } 
      } 
     }; 
     return simTracker; 
    } 

,這是VisualTrackingParticipant

public class VisualTrackingParticipant : System.Activities.Tracking.TrackingParticipant 
{ 
    public event EventHandler<TrackingEventArgs> TrackingRecordReceived; 
    public Dictionary<string, Activity> ActivityIdToWorkflowElementMap { get; set; } 


    protected override void Track(TrackingRecord record, TimeSpan timeout) 
    { 
     OnTrackingRecordReceived(record, timeout); 
    } 

    //On Tracing Record Received call the TrackingRecordReceived with the record received information from the TrackingParticipant. 
    //We also do not worry about Expressions' tracking data 
    protected void OnTrackingRecordReceived(TrackingRecord record, TimeSpan timeout) 
    { 
     System.Diagnostics.Debug.WriteLine(
      String.Format("Tracking Record Received: {0} with timeout: {1} seconds.", record, timeout.TotalSeconds) 
     ); 

     if (TrackingRecordReceived != null) 
     { 
      ActivityStateRecord activityStateRecord = record as ActivityStateRecord; 

      if//(
       (activityStateRecord != null) 
      // && (!activityStateRecord.Activity.TypeName.Contains("System.Activities.Expressions"))) 
      { 
       Activity act = null; 
       ActivityIdToWorkflowElementMap.TryGetValue(activityStateRecord.Activity.Id, out act); 


       TrackingRecordReceived(this, new TrackingEventArgs(
               record, 
               timeout, 
               act 
               ) 

        ); 


      } 
      else 
      { 
       TrackingRecordReceived(this, new TrackingEventArgs(record, timeout, null)); 
      } 

     } 
    } 
} 

//Custom Tracking EventArgs 
public class TrackingEventArgs : EventArgs 
{ 
    public TrackingRecord Record {get; set;} 
    public TimeSpan Timeout {get; set;} 
    public Activity Activity { get; set; } 

    public TrackingEventArgs(TrackingRecord trackingRecord, TimeSpan timeout, Activity activity) 
    { 
     this.Record = trackingRecord; 
     this.Timeout = timeout; 
     this.Activity = activity; 
    } 
} 

如果我跟蹤這個WF:

<Activity mc:Ignorable="sap" x:Class="Microsoft.Samples.Workflow" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sd1="clr-namespace:System.Data;assembly=System.Data.DataSetExtensions" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <x:Members> 
    <x:Property Name="decisionVar" Type="InArgument(x:Boolean)" /> 
    </x:Members> 
    <sap:VirtualizedContainerService.HintSize>666,676</sap:VirtualizedContainerService.HintSize> 
    <mva:VisualBasic.Settings>Assembly references and imported namespaces serialized as XML namespaces</mva:VisualBasic.Settings> 
    <Flowchart sad:XamlDebuggerXmlReader.FileName="C:\WF_WCF_Samples\WF\Application\VisualWorkflowTracking\CS\VisualWorkflowTracking\Workflow.xaml" sap:VirtualizedContainerService.HintSize="626,636" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces"> 
    <Flowchart.Variables> 
     <Variable x:TypeArguments="x:String" Name="myStr" /> 
    </Flowchart.Variables> 
    <sap:WorkflowViewStateService.ViewState> 
     <scg3:Dictionary x:TypeArguments="x:String, x:Object"> 
     <x:Boolean x:Key="IsExpanded">False</x:Boolean> 
     <av:Point x:Key="ShapeLocation">270,7.5</av:Point> 
     <av:Size x:Key="ShapeSize">60,75</av:Size> 
     <av:PointCollection x:Key="ConnectorLocation">300,82.5 300,111.5</av:PointCollection> 
     <x:Double x:Key="Width">611.5</x:Double> 
     </scg3:Dictionary> 
    </sap:WorkflowViewStateService.ViewState> 
    <Flowchart.StartNode> 
     <FlowStep x:Name="__ReferenceID0"> 
     <sap:WorkflowViewStateService.ViewState> 
      <scg3:Dictionary x:TypeArguments="x:String, x:Object"> 
      <av:Point x:Key="ShapeLocation">179,111.5</av:Point> 
      <av:Size x:Key="ShapeSize">242,58</av:Size> 
      <av:PointCollection x:Key="ConnectorLocation">300,169.5 300,199.5 280,199.5 280,269.5</av:PointCollection> 
      </scg3:Dictionary> 
     </sap:WorkflowViewStateService.ViewState> 
     <Assign sap:VirtualizedContainerService.HintSize="242,58"> 
      <Assign.To> 
      <OutArgument x:TypeArguments="x:String">[myStr]</OutArgument> 
      </Assign.To> 
      <Assign.Value> 
      <InArgument x:TypeArguments="x:String">PDC Rocks</InArgument> 
      </Assign.Value> 
     </Assign> 
     <FlowStep.Next> 
      <FlowStep x:Name="__ReferenceID1"> 
      <sap:WorkflowViewStateService.ViewState> 
       <scg3:Dictionary x:TypeArguments="x:String, x:Object"> 
       <av:Point x:Key="ShapeLocation">174.5,269.5</av:Point> 
       <av:Size x:Key="ShapeSize">211,61</av:Size> 
       <av:PointCollection x:Key="ConnectorLocation">155.33,351.361666666667 155.33,481 204.5,481</av:PointCollection> 
       </scg3:Dictionary> 
      </sap:WorkflowViewStateService.ViewState> 
      <WriteLine sap:VirtualizedContainerService.HintSize="211,61" Text="[myStr]" /> 
      </FlowStep> 
     </FlowStep.Next> 
     </FlowStep> 
    </Flowchart.StartNode> 
    <x:Reference>__ReferenceID0</x:Reference> 
    <x:Reference>__ReferenceID1</x:Reference> 
    </Flowchart> 
</Activity> 

當activitity assing接近ÿrecive此追蹤此參數

[參數]值= PDC巖 [參數]爲了= PDC岩石

,我不知道哪裏的VAR值assined