Dictionary <object, SourceLocation> GetErrorInformation(Activity activity) { Dictionary <object, SourceLocation> sourceLocations = null; Activity implementationRoot = null; IEnumerable <Activity> children = WorkflowInspectionServices.GetActivities(activity); foreach (Activity child in children) { // Check if the child is the root of the activity's implementation // When an activity is an implementation child of another activity, the IDSpace for // the implementation child is different than it's parent activity and parent's public // children. The IDs for activities in the root activity's IDSpace are 1, 2 // etc and for the root implementation child it is 1.1 and for its implementation // child it is 1.1.1 and so on. // As the activity can have just one implementation root, we just check // for '.' to identify the root of the implementation. if (child.Id.Contains(".")) { implementationRoot = child; break; } } if (implementationRoot == null) { return(sourceLocations); } // We use the workflow debug symbol to get the line and column number information for a // erroneous activity. // We do not rely on the workflow debug symbol to get the file name. This is to enable cases // where the xaml was hand written outside of the workflow designer. The hand written xaml // file will not have the workflow debug symbol unless it was saved in the workflow designer. string symbolString = DebugSymbol.GetSymbol(implementationRoot) as String; if (!string.IsNullOrEmpty(symbolString)) { try { WorkflowSymbol wfSymbol = WorkflowSymbol.Decode(symbolString); if (wfSymbol != null) { sourceLocations = SourceLocationProvider.GetSourceLocations(activity, wfSymbol); } } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } // Ignore invalid symbol. } } return(sourceLocations); }
// Collect subroot as uninstrumented activity. void CollectSubRoot(Activity activity) { string wfSymbol = DebugSymbol.GetSymbol(activity) as string; if (!string.IsNullOrEmpty(wfSymbol)) { this.uninstrumentedSubRoots.Add(activity, wfSymbol); } else { string sourcePath = XamlDebuggerXmlReader.GetFileName(activity) as string; if (!string.IsNullOrEmpty(sourcePath)) { this.uninstrumentedSubRoots.Add(activity, sourcePath); } } }
static internal Dictionary <object, SourceLocation> GetSourceLocations(Activity rootActivity, out string sourcePath, out bool isTemporaryFile, out byte[] checksum) { isTemporaryFile = false; checksum = null; string symbolString = DebugSymbol.GetSymbol(rootActivity) as String; if (string.IsNullOrEmpty(symbolString) && rootActivity.Children != null && rootActivity.Children.Count > 0) { // In case of actual root is wrapped either in x:Class activity or CorrelationScope Activity body = rootActivity.Children[0]; string bodySymbolString = DebugSymbol.GetSymbol(body) as String; if (!string.IsNullOrEmpty(bodySymbolString)) { rootActivity = body; symbolString = bodySymbolString; } } if (!string.IsNullOrEmpty(symbolString)) { try { WorkflowSymbol wfSymbol = WorkflowSymbol.Decode(symbolString); if (wfSymbol != null) { sourcePath = wfSymbol.FileName; checksum = wfSymbol.GetChecksum(); // rootActivity is the activity with the attached symbol string. // rootActivity.RootActivity is the workflow root activity. // if they are not the same, then it must be compiled XAML, because loose XAML (i.e. XAMLX) always have the symbol attached at the root. if (rootActivity.RootActivity != rootActivity) { Fx.Assert(rootActivity.Parent != null, "Compiled XAML implementation always have a parent."); rootActivity = rootActivity.Parent; } return(GetSourceLocations(rootActivity, wfSymbol, translateInternalActivityToOrigin: false)); } } catch (SerializationException) { // Ignore invalid symbol. } } sourcePath = XamlDebuggerXmlReader.GetFileName(rootActivity) as string; Dictionary <object, SourceLocation> mapping; Assembly localAssembly; //bool permissionRevertNeeded = false; // This may not be the local assembly since it may not be the real root for x:Class localAssembly = rootActivity.GetType().Assembly; if (rootActivity.Parent != null) { localAssembly = rootActivity.Parent.GetType().Assembly; } if (rootActivity.Children != null && rootActivity.Children.Count > 0) { // In case of actual root is wrapped either in x:Class activity or CorrelationScope Activity body = rootActivity.Children[0]; string bodySourcePath = XamlDebuggerXmlReader.GetFileName(body) as string; if (!string.IsNullOrEmpty(bodySourcePath)) { rootActivity = body; sourcePath = bodySourcePath; } } try { Fx.Assert(!string.IsNullOrEmpty(sourcePath), "If sourcePath is null, it should have been short-circuited before reaching here."); SourceLocation tempSourceLocation; Activity tempRootActivity; checksum = SymbolHelper.CalculateChecksum(sourcePath); if (TryGetSourceLocation(rootActivity, sourcePath, checksum, out tempSourceLocation)) // already has source location. { tempRootActivity = rootActivity; } else { byte[] buffer; #if NET45 // Need to store the file in memory temporary so don't have to re-read the file twice // for XamlDebugXmlReader's BracketLocator. // If there is a debugger attached, Assert FileIOPermission for Read access to the specific file. if (System.Diagnostics.Debugger.IsAttached) { permissionRevertNeeded = true; FileIOPermission permission = new FileIOPermission(FileIOPermissionAccess.Read, sourcePath); permission.Assert(); } #endif try { FileInfo fi = new FileInfo(sourcePath); buffer = new byte[fi.Length]; using (FileStream fs = new FileStream(sourcePath, FileMode.Open, FileAccess.Read)) { fs.Read(buffer, 0, buffer.Length); } } finally { #if NET45 // If we Asserted FileIOPermission, revert it. if (permissionRevertNeeded) { CodeAccessPermission.RevertAssert(); permissionRevertNeeded = false; } #endif } object deserializedObject = Deserialize(buffer, localAssembly); IDebuggableWorkflowTree debuggableWorkflowTree = deserializedObject as IDebuggableWorkflowTree; if (debuggableWorkflowTree != null) { // Declarative Service and x:Class case tempRootActivity = debuggableWorkflowTree.GetWorkflowRoot(); } else { // Loose XAML case. tempRootActivity = deserializedObject as Activity; } Fx.Assert(tempRootActivity != null, "Unexpected workflow xaml file"); } mapping = new Dictionary <object, SourceLocation>(); if (tempRootActivity != null) { CollectMapping(rootActivity, tempRootActivity, mapping, sourcePath, checksum); } } catch (Exception) { //// Only eat the exception if we were running in partial trust. //if (!PartialTrustHelpers.AppDomainFullyTrusted) //{ // // Eat the exception and return an empty dictionary. // return new Dictionary<object, SourceLocation>(); //} //else //{ throw; //} } return(mapping); }