// Get the attached workflow symbol and remove it from the root. WorkflowSymbol GetAttachedWorkflowSymbol() { object rootInstance = this.GetRootInstance(); WorkflowSymbol wfSymbol = null; if (rootInstance != null) { Activity documentRootElement = GetRootWorkflowElement(rootInstance); if (documentRootElement != null) { string symbolString; if (AttachablePropertyServices.TryGetProperty <string>(documentRootElement, DebugSymbol.SymbolName, out symbolString)) { try { wfSymbol = WorkflowSymbol.Decode(symbolString); // Change the name to the currently loaded file. wfSymbol.FileName = this.Context.Items.GetValue <WorkflowFileItem>().LoadedFile; } catch (Exception ex) { if (Fx.IsFatal(ex)) { throw; } } finally { AttachablePropertyServices.RemoveProperty(documentRootElement, DebugSymbol.SymbolName); } } } } return(wfSymbol); }
public void Load(string fileName) { if (string.IsNullOrEmpty(fileName)) { throw FxTrace.Exception.AsError(new ArgumentNullException("fileName")); } DesignerConfigurationService service = this.Context.Services.GetService <DesignerConfigurationService>(); service.SetDefaultOfLoadingFromUntrustedSourceEnabled(); if (!service.LoadingFromUntrustedSourceEnabled && !IsFromUnrestrictedPath(fileName)) { throw FxTrace.Exception.AsError(new SecurityException(string.Format(CultureInfo.CurrentUICulture, SR.UntrustedSourceDetected, fileName))); } try { IDocumentPersistenceService documentPersistenceService = this.Context.Services.GetService <IDocumentPersistenceService>(); if (documentPersistenceService != null) { this.Load(documentPersistenceService.Load(fileName)); } else { using (StreamReader fileStream = new StreamReader(fileName)) { this.loadedFile = fileName; WorkflowFileItem fileItem = new WorkflowFileItem(); fileItem.LoadedFile = fileName; this.context.Items.SetValue(fileItem); this.Text = fileStream.ReadToEnd(); this.Load(); } } } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } else { this.Context.Items.SetValue(new ErrorItem() { Message = e.Message, Details = e.ToString() }); } } if (!this.IsInErrorState()) { this.lastWorkflowSymbol = GetAttachedWorkflowSymbol(); if (this.debuggerService != null) { this.debuggerService.InvalidateSourceLocationMapping(fileName); } } }
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); }
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); }
// For most of the time, we need source location for object that appear on XAML. // During debugging, however, we must not transform the internal activity to their origin to make sure it stop when the internal activity is about the execute // Therefore, in debugger scenario, translateInternalActivityToOrigin will be set to false. internal static Dictionary <object, SourceLocation> GetSourceLocations(Activity rootActivity, WorkflowSymbol symbol, bool translateInternalActivityToOrigin) { Activity workflowRoot = rootActivity.RootActivity ?? rootActivity; if (!workflowRoot.IsMetadataFullyCached) { IList <ValidationError> validationErrors = null; ActivityUtilities.CacheRootMetadata(workflowRoot, new ActivityLocationReferenceEnvironment(), ProcessActivityTreeOptions.ValidationOptions, null, ref validationErrors); } Dictionary <object, SourceLocation> newMapping = new Dictionary <object, SourceLocation>(); // Make sure the qid we are using to TryGetElementFromRoot // are shifted appropriately such that the first digit that QID is // the same as the last digit of the rootActivity.QualifiedId. int[] rootIdArray = rootActivity.QualifiedId.AsIDArray(); int idOffset = rootIdArray[rootIdArray.Length - 1] - 1; foreach (ActivitySymbol actSym in symbol.Symbols) { QualifiedId qid = new QualifiedId(actSym.QualifiedId); if (idOffset != 0) { int[] idArray = qid.AsIDArray(); idArray[0] += idOffset; qid = new QualifiedId(idArray); } Activity activity; if (QualifiedId.TryGetElementFromRoot(rootActivity, qid, out activity)) { object origin = activity; if (translateInternalActivityToOrigin && activity.Origin != null) { origin = activity.Origin; } newMapping.Add(origin, new SourceLocation(symbol.FileName, symbol.GetChecksum(), actSym.StartLine, actSym.StartColumn, actSym.EndLine, actSym.EndColumn)); } } return(newMapping); }
public static Dictionary <object, SourceLocation> GetSourceLocations(Activity rootActivity, WorkflowSymbol symbol) { return(GetSourceLocations(rootActivity, symbol, translateInternalActivityToOrigin: true)); }
// This supports loading objects instead of xaml into the designer public void Load(object instance) { if (isLoaded) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.WorkflowDesignerLoadShouldBeCalledOnlyOnce)); } isLoaded = true; if (instance == null) { throw FxTrace.Exception.AsError(new ArgumentNullException("instance")); } DesignerConfigurationService configurationService = this.context.Services.GetService <DesignerConfigurationService>(); configurationService.ApplyDefaultPreference(); // Because we want AutoConnect/AutoSplit to be on even in Dev10 if PU1 is installed. // But we cannot know whether PU1 is installed or not, we decide to enable these 2 features for all Dev10. if (configurationService.WorkflowDesignerHostId == WorkflowDesignerHostId.Dev10) { configurationService.AutoConnectEnabled = true; configurationService.AutoSplitEnabled = true; } configurationService.IsWorkflowLoaded = true; configurationService.Validate(); if (this.PreviewLoad != null) { this.PreviewLoad(this, new PreviewLoadEventArgs(instance, this.context)); } if (configurationService.TargetFrameworkName.IsLessThan45()) { TargetFrameworkPropertyFilter.FilterOut45Properties(); } modelTreeManager = new ModelTreeManager(this.context); modelTreeManager.Load(instance); this.context.Services.Publish(typeof(ModelTreeManager), modelTreeManager); viewManager = GetViewManager(this.modelTreeManager.Root); this.context.Services.Publish <ModelSearchService>(this.ModelSearchService); view.Children.Add((UIElement)viewManager.View); modelTreeManager.EditingScopeCompleted += new EventHandler <EditingScopeEventArgs>(OnEditingScopeCompleted); this.view.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { this.perfEventProvider.WorkflowDesignerApplicationIdleAfterLoad(); })); //Subscribe to the ViewStateChanged event of ViewStateService to show document dirty. It would be published in the call to GetViewManager(). WorkflowViewStateService wfViewStateService = this.Context.Services.GetService(typeof(ViewStateService)) as WorkflowViewStateService; if (wfViewStateService != null) { wfViewStateService.UndoableViewStateChanged += new ViewStateChangedEventHandler(OnViewStateChanged); } this.isModelChanged = false; if (!this.IsInErrorState()) { this.lastWorkflowSymbol = GetAttachedWorkflowSymbol(); } }
public void Load() { this.perfEventProvider.WorkflowDesignerLoadStart(); if (!string.IsNullOrEmpty(this.text)) { try { this.perfEventProvider.WorkflowDesignerDeserializeStart(); IList <XamlLoadErrorInfo> loadErrors; Dictionary <object, SourceLocation> sourceLocations; object deserializedObject = DeserializeString(this.text, out loadErrors, out sourceLocations); this.perfEventProvider.WorkflowDesignerDeserializeEnd(); if (deserializedObject != null) { this.Load(deserializedObject); this.ValidationService.ValidateWorkflow(ValidationReason.Load); } else { StringBuilder details = new StringBuilder(); foreach (XamlLoadErrorInfo error in loadErrors) { details.AppendLine(error.Message); } this.Context.Items.SetValue(new ErrorItem() { Message = SR.SeeErrorWindow, Details = details.ToString() }); } if (loadErrors != null) { RaiseLoadErrors(loadErrors); } this.isModelChanged = false; } catch (Exception e) { this.Context.Items.SetValue(new ErrorItem() { Message = e.Message, Details = e.ToString() }); RaiseLoadError(e); } } else { this.Context.Items.SetValue(new ErrorItem() { Message = string.Empty, Details = string.Empty }); } if (this.IsInErrorState()) { // Clear workflow symbol in case ErrorState changes during validation this.lastWorkflowSymbol = null; } this.perfEventProvider.WorkflowDesignerLoadComplete(); }
private void UpdateDebugSymbol(ClassData classData, XamlBuildTypeGenerationExtensionContext buildContext) { string path = Path.GetFullPath(classData.FileName); try { using (XamlReader reader = classData.EmbeddedResourceXaml.GetReader()) { XamlNodeList newList = new XamlNodeList(reader.SchemaContext); using (XamlWriter writer = newList.Writer) { bool nodesAvailable = reader.Read(); while (nodesAvailable) { if (reader.NodeType == XamlNodeType.StartMember) { writer.WriteNode(reader); if (reader.Member.DeclaringType != null && reader.Member.DeclaringType.UnderlyingType != null && string.CompareOrdinal(reader.Member.DeclaringType.UnderlyingType.FullName, debugSymbolTypeFullName) == 0) { reader.Read(); string symbolString = reader.Value as string; if (!string.IsNullOrEmpty(symbolString)) { WorkflowSymbol symbol = WorkflowSymbol.Decode(symbolString); symbol.FileName = path; symbol.CalculateChecksum(); writer.WriteValue(symbol.Encode()); } else { writer.WriteValue(reader.Value); } } nodesAvailable = reader.Read(); } else { writer.WriteNode(reader); nodesAvailable = reader.Read(); } } } classData.EmbeddedResourceXaml = newList; } } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } buildContext.XamlBuildLogger.LogMessage( MessageImportance.High, SR.DebugBuildExtensionExceptionPrefix( typeof(DebugBuildExtension).Name, path, e.Message)); } }