Exemple #1
0
            private PluginContext CreatePluginContext(PluginContext pluginContext, Guid guid, string logicalName, Entity preImage, Entity postImage)
            {
                var thisPluginContext = pluginContext.Clone();

                thisPluginContext.Mode  = (int)this.mode;
                thisPluginContext.Stage = (int)this.stage;
                if (thisPluginContext.PrimaryEntityId == Guid.Empty)
                {
                    thisPluginContext.PrimaryEntityId = guid;
                }
                thisPluginContext.PrimaryEntityName = logicalName;

                foreach (var image in this.images)
                {
                    var type = (ImageType)image.Item3;
                    var cols = image.Item4 != null ? new ColumnSet(image.Item4.Split(',')) : new ColumnSet(true);
                    if (postImage != null && stage == ExecutionStage.PostOperation && (type == ImageType.PostImage || type == ImageType.Both))
                    {
                        thisPluginContext.PostEntityImages.Add(image.Item1, postImage.CloneEntity(metadata.GetMetadata(postImage.LogicalName), cols));
                    }
                    if (preImage != null && type == ImageType.PreImage || type == ImageType.Both)
                    {
                        thisPluginContext.PreEntityImages.Add(image.Item1, preImage.CloneEntity(metadata.GetMetadata(preImage.LogicalName), cols));
                    }
                }
                return(thisPluginContext);
            }
        private PluginContext createPluginContext(PluginContext pluginContext, Entity workflow, workflow_stage?thisStage, Guid guid, string logicalName)
        {
            var thisPluginContext = pluginContext.Clone();

            thisPluginContext.Mode              = ((int)workflow.GetOptionSetValue <Workflow_Mode>("mode") + 1) % 2;
            thisPluginContext.Stage             = thisStage.HasValue ? (int)thisStage : (int)workflow_stage.Postoperation;
            thisPluginContext.PrimaryEntityId   = guid;
            thisPluginContext.PrimaryEntityName = logicalName;

            return(thisPluginContext);
        }
Exemple #3
0
        internal OrganizationResponse Execute(OrganizationRequest request, EntityReference userRef, PluginContext parentPluginContext)
        {
            // Setup
            HandleInternalPreOperations(request, userRef);

            var primaryRef = Mappings.GetPrimaryEntityReferenceFromRequest(request);

            // Create the plugin context
            var pluginContext = new PluginContext()
            {
                UserId            = userRef.Id,
                InitiatingUserId  = userRef.Id,
                MessageName       = RequestNameToMessageName(request.RequestName),
                Depth             = 1,
                OrganizationName  = this.OrganizationName,
                OrganizationId    = this.OrganizationId,
                PrimaryEntityName = primaryRef?.LogicalName,
            };

            if (primaryRef != null)
            {
                var refEntity = db.GetEntityOrNull(primaryRef);
                pluginContext.PrimaryEntityId = refEntity == null ? Guid.Empty : refEntity.Id;
            }

            foreach (var prop in request.Parameters)
            {
                pluginContext.InputParameters[prop.Key] = prop.Value;
            }
            if (parentPluginContext != null)
            {
                pluginContext.ParentContext = parentPluginContext;
                pluginContext.Depth         = parentPluginContext.Depth + 1;
            }
            var buRef = GetBusinessUnit(userRef);

            pluginContext.BusinessUnitId = buRef.Id;

            Mappings.RequestToEventOperation.TryGetValue(request.GetType(), out EventOperation? eventOp);

            var entityInfo = GetEntityInfo(request);

            var settings = MockupExecutionContext.GetSettings(request);

            // Validation
            if (!settings.SetUnsettableFields && (request is UpdateRequest || request is CreateRequest))
            {
                var entity = request is UpdateRequest ? (request as UpdateRequest).Target : (request as CreateRequest).Target;
                Utility.RemoveUnsettableAttributes(request.RequestName, metadata.EntityMetadata.GetMetadata(entity.LogicalName), entity);
            }

            Entity preImage  = null;
            Entity postImage = null;

            if (settings.TriggerProcesses && entityInfo != null)
            {
                preImage = TryRetrieve(primaryRef);
                if (preImage != null)
                {
                    primaryRef.Id = preImage.Id;
                }
            }

            if (settings.TriggerProcesses && entityInfo != null && eventOp.HasValue)
            {
                // System Pre-validation
                pluginManager.TriggerSystem(eventOp.Value, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                // Pre-validation
                pluginManager.Trigger(eventOp.Value, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                // Shared variables should be moved to parent context when transitioning from 10 to 20.
                pluginContext.ParentContext = pluginContext.Clone();
                pluginContext.SharedVariables.Clear();

                // Pre-operation
                pluginManager.Trigger(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                workflowManager.Trigger(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                // System Pre-operation
                pluginManager.TriggerSystem(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
            }

            // Core operation
            OrganizationResponse response = ExecuteRequest(request, userRef, parentPluginContext);

            // Post-operation
            if (settings.TriggerProcesses && entityInfo != null)
            {
                postImage = TryRetrieve(primaryRef);
                if (eventOp.HasValue)
                {
                    pluginManager.TriggerSystem(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    pluginManager.Trigger(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    workflowManager.Trigger(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                }
                workflowManager.ExecuteWaitingWorkflows(pluginContext, this);
            }

            return(response);
        }
Exemple #4
0
            public void ExecuteIfMatch(object entityObject, Entity preImage, Entity postImage, PluginContext pluginContext, Core core)
            {
                // Check if it is supposed to execute. Returns preemptively, if it should not.
                var entity    = entityObject as Entity;
                var entityRef = entityObject as EntityReference;

                var guid        = (entity != null) ? entity.Id : entityRef.Id;
                var logicalName = (entity != null) ? entity.LogicalName : entityRef.LogicalName;

                if (entityName != "" && entityName != logicalName)
                {
                    return;
                }

                if (entity != null && metadata.GetMetadata(logicalName)?.PrimaryIdAttribute != null)
                {
                    entity[metadata.GetMetadata(logicalName).PrimaryIdAttribute] = guid;
                }

                if (pluginContext.Depth > 8)
                {
                    throw new FaultException(
                              "This workflow job was canceled because the workflow that started it included an infinite loop." +
                              " Correct the workflow logic and try again.");
                }

                if (operation == EventOperation.Update && stage == ExecutionStage.PostOperation)
                {
                    var shadowAddedAttributes = postImage.Attributes.Where(a => !preImage.Attributes.ContainsKey(a.Key) && !entity.Attributes.ContainsKey(a.Key));
                    entity = entity.CloneEntity();
                    entity.Attributes.AddRange(shadowAddedAttributes);
                }

                if (operation == EventOperation.Update && attributes.Count > 0)
                {
                    var foundAttr = false;
                    foreach (var attr in entity.Attributes)
                    {
                        if (attributes.Contains(attr.Key))
                        {
                            foundAttr = true;
                            break;
                        }
                    }
                    if (!foundAttr)
                    {
                        return;
                    }
                }

                if (entityName != "" && (operation == EventOperation.Associate || operation == EventOperation.Disassociate))
                {
                    throw new MockupException(
                              $"An {operation} plugin step was registered for a specific entity, which can only be registered on AnyEntity");
                }

                // Create the plugin context
                var thisPluginContext = pluginContext.Clone();

                thisPluginContext.Mode  = (int)this.mode;
                thisPluginContext.Stage = (int)this.stage;
                if (thisPluginContext.PrimaryEntityId == Guid.Empty)
                {
                    thisPluginContext.PrimaryEntityId = guid;
                }
                thisPluginContext.PrimaryEntityName = logicalName;

                foreach (var image in this.images)
                {
                    var type = (ImageType)image.Item3;
                    var cols = image.Item4 != null ? new ColumnSet(image.Item4.Split(',')) : new ColumnSet(true);
                    if (postImage != null && stage == ExecutionStage.PostOperation && (type == ImageType.PostImage || type == ImageType.Both))
                    {
                        thisPluginContext.PostEntityImages.Add(image.Item1, postImage.CloneEntity(metadata.GetMetadata(postImage.LogicalName), cols));
                    }
                    if (preImage != null && type == ImageType.PreImage || type == ImageType.Both)
                    {
                        thisPluginContext.PreEntityImages.Add(image.Item1, preImage.CloneEntity(metadata.GetMetadata(preImage.LogicalName), cols));
                    }
                }

                // Create service provider and execute the plugin
                MockupServiceProviderAndFactory provider = new MockupServiceProviderAndFactory(core, thisPluginContext, new TracingService());

                try {
                    pluginExecute(provider);
                } catch (TargetInvocationException e) {
                    ExceptionDispatchInfo.Capture(e.InnerException).Throw();
                }
            }
Exemple #5
0
        internal OrganizationResponse Execute(OrganizationRequest request, EntityReference userRef, PluginContext parentPluginContext)
        {
            // Setup
            HandleInternalPreOperations(request, userRef);

            var primaryRef = Mappings.GetPrimaryEntityReferenceFromRequest(request);

            // Create the plugin context
            var pluginContext = new PluginContext()
            {
                UserId            = userRef.Id,
                InitiatingUserId  = userRef.Id,
                MessageName       = RequestNameToMessageName(request.RequestName),
                Depth             = 1,
                OrganizationName  = this.OrganizationName,
                OrganizationId    = this.OrganizationId,
                PrimaryEntityName = primaryRef?.LogicalName,
            };

            if (primaryRef != null)
            {
                var refEntity = db.GetEntityOrNull(primaryRef);
                pluginContext.PrimaryEntityId = refEntity == null ? Guid.Empty : refEntity.Id;
            }

            foreach (var prop in request.Parameters)
            {
                pluginContext.InputParameters[prop.Key] = prop.Value;
            }
            if (parentPluginContext != null)
            {
                pluginContext.ParentContext = parentPluginContext;
                pluginContext.Depth         = parentPluginContext.Depth + 1;
            }
            var buRef = GetBusinessUnit(userRef);

            pluginContext.BusinessUnitId = buRef.Id;

            Mappings.RequestToEventOperation.TryGetValue(request.GetType(), out string eventOp);
            if (string.IsNullOrEmpty(eventOp))
            {
                //then this may be a custom action request, so continue with the request name
                if (request.RequestName.Contains("_")) //if we have a prefix then assume it is a custom action
                {
                    eventOp = request.RequestName.ToLower();
                }
            }


            var entityInfo = GetEntityInfo(request);

            var settings = MockupExecutionContext.GetSettings(request);

            // Validation
            if (!settings.SetUnsettableFields && (request is UpdateRequest || request is CreateRequest))
            {
                var entity = request is UpdateRequest ? (request as UpdateRequest).Target : (request as CreateRequest).Target;
                Utility.RemoveUnsettableAttributes(request.RequestName, metadata.EntityMetadata.GetMetadata(entity.LogicalName), entity);
            }

            Entity preImage  = null;
            Entity postImage = null;

            if (settings.TriggerProcesses && entityInfo != null)
            {
                preImage = TryRetrieve(primaryRef);
                if (preImage != null)
                {
                    primaryRef.Id = preImage.Id;
                }
            }

            if (settings.TriggerProcesses && entityInfo != null && !string.IsNullOrEmpty(eventOp))
            {
                // System Pre-validation
                pluginManager.TriggerSystem(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                // Pre-validation
                pluginManager.Trigger(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                // Shared variables should be moved to parent context when transitioning from 10 to 20.
                pluginContext.ParentContext = pluginContext.Clone();
                pluginContext.SharedVariables.Clear();

                // Pre-operation
                pluginManager.Trigger(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                workflowManager.TriggerSync(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                // System Pre-operation
                pluginManager.TriggerSystem(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
            }

            // Core operation
            OrganizationResponse response = ExecuteRequest(request, userRef, parentPluginContext);

            // Post-operation
            if (settings.TriggerProcesses && entityInfo != null)
            {
                postImage = TryRetrieve(primaryRef);

                // In RetrieveMultipleRequests, the OutputParameters bag contains the entity collection
                if (request is RetrieveMultipleRequest)
                {
                    pluginContext.OutputParameters["BusinessEntityCollection"] = (response as RetrieveMultipleResponse)?.EntityCollection;
                }

                if (!string.IsNullOrEmpty(eventOp))
                {
                    //copy the createon etc system attributes onto the target so they are available for postoperation processing
                    CopySystemAttributes(postImage, entityInfo.Item1 as Entity);

                    pluginManager.TriggerSystem(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    pluginManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    pluginManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                    workflowManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    workflowManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                }

                //When last Sync has been executed we trigger the Async jobs.
                if (parentPluginContext == null)
                {
                    pluginManager.TriggerAsyncWaitingJobs();
                    workflowManager.TriggerAsync(this);
                }
                workflowManager.ExecuteWaitingWorkflows(pluginContext, this);
            }
            return(response);
        }
Exemple #6
0
        internal OrganizationResponse Execute(OrganizationRequest request, EntityReference userRef,
                                              PluginContext parentPluginContext)
        {
            // Setup
            HandleInternalPreOperations(request, userRef);

            var primaryRef = Mappings.GetPrimaryEntityReferenceFromRequest(request);

            // Create the plugin context
            var pluginContext = new PluginContext()
            {
                UserId            = userRef.Id,
                InitiatingUserId  = userRef.Id,
                MessageName       = RequestNameToMessageName(request.RequestName),
                Depth             = 1,
                ExtensionDepth    = 1,
                OrganizationName  = this.OrganizationName,
                OrganizationId    = this.OrganizationId,
                PrimaryEntityName = primaryRef?.LogicalName,
            };

            if (primaryRef != null)
            {
                var refEntity = db.GetEntityOrNull(primaryRef);
                pluginContext.PrimaryEntityId = refEntity == null ? Guid.Empty : refEntity.Id;
            }

            foreach (var prop in request.Parameters)
            {
                pluginContext.InputParameters[prop.Key] = prop.Value;
            }

            if (parentPluginContext != null)
            {
                pluginContext.ParentContext        = parentPluginContext;
                pluginContext.Depth                = parentPluginContext.Depth + 1;
                pluginContext.ExtensionDepth       = parentPluginContext.ExtensionDepth + 1;
                parentPluginContext.ExtensionDepth = pluginContext.ExtensionDepth;
            }

            var buRef = GetBusinessUnit(userRef);

            pluginContext.BusinessUnitId = buRef.Id;

            Mappings.RequestToEventOperation.TryGetValue(request.GetType(), out string eventOp);

            var entityInfo = GetEntityInfo(request);

            var settings = MockupExecutionContext.GetSettings(request);

            // Validation
            if (!settings.SetUnsettableFields && (request is UpdateRequest || request is CreateRequest))
            {
                var entity = request is UpdateRequest
                    ? (request as UpdateRequest).Target
                    : (request as CreateRequest).Target;
                Utility.RemoveUnsettableAttributes(request.RequestName,
                                                   metadata.EntityMetadata.GetMetadata(entity.LogicalName), entity);
            }

            Entity preImage  = null;
            Entity postImage = null;

            if (settings.TriggerProcesses && entityInfo != null)
            {
                preImage = TryRetrieve(primaryRef);
                if (preImage != null)
                {
                    primaryRef.Id = preImage.Id;
                }
            }

            if (settings.TriggerProcesses && entityInfo != null)
            {
                // System Pre-validation
                pluginManager.TriggerSystem(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                // Pre-validation
                pluginManager.Trigger(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);
            }

            //perform security checks for the request
            CheckRequestSecurity(request, userRef);

            if (settings.TriggerProcesses && entityInfo != null)
            {
                // Shared variables should be moved to parent context when transitioning from 10 to 20.
                pluginContext.ParentContext = pluginContext.Clone();
                pluginContext.SharedVariables.Clear();

                // Pre-operation
                pluginManager.Trigger(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                workflowManager.TriggerSync(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                // System Pre-operation
                pluginManager.TriggerSystem(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
            }

            // Core operation
            OrganizationResponse response = ExecuteRequest(request, userRef, parentPluginContext);

            // Post-operation
            if (settings.TriggerProcesses && entityInfo != null)
            {
                postImage = TryRetrieve(primaryRef);

                // In RetrieveMultipleRequests, the OutputParameters bag contains the entity collection
                if (request is RetrieveMultipleRequest)
                {
                    pluginContext.OutputParameters["BusinessEntityCollection"] =
                        (response as RetrieveMultipleResponse)?.EntityCollection;
                }

                if (!string.IsNullOrEmpty(eventOp))
                {
                    //copy the createon etc system attributes onto the target so they are available for postoperation processing
                    CopySystemAttributes(postImage, entityInfo.Item1 as Entity);

                    pluginManager.TriggerSystem(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    pluginManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    pluginManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                    workflowManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    workflowManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                }

                //When last Sync has been executed we trigger the Async jobs.
                if (parentPluginContext == null)
                {
                    pluginManager.TriggerAsyncWaitingJobs();
                    workflowManager.TriggerAsync(this);
                }

                workflowManager.ExecuteWaitingWorkflows(pluginContext, this);
            }

#if XRM_MOCKUP_365
            // Trigger Extension
            if (this.settings.MockUpExtensions.Any())
            {
                /*
                 * When moving business units, more than eight layers occur...
                 */
                if (pluginContext.ExtensionDepth > 8)
                {
                    throw new FaultException(
                              "This workflow job was canceled because the workflow that started it included an infinite loop." +
                              " Correct the workflow logic and try again.");
                }
            }

            switch (request.RequestName)
            {
            case "Create":
                var createResponse    = (CreateResponse)response;
                var entityLogicalName = ((Entity)request.Parameters["Target"]).LogicalName;

                var createdEntity =
                    GetDbRow(new EntityReference(entityLogicalName, createResponse.id))
                    .ToEntity();
                TriggerExtension(
                    new XrmExtension(this, userRef, pluginContext), request,
                    createdEntity, null, userRef);
                break;

            case "Update":
                var target        = (Entity)request.Parameters["Target"];
                var updatedEntity = GetDbRow(target.ToEntityReferenceWithKeyAttributes()).ToEntity();
                TriggerExtension(
                    new XrmExtension(this, userRef, pluginContext), request,
                    updatedEntity, preImage, userRef);
                break;

            case "Delete":
                TriggerExtension(
                    new XrmExtension(this, userRef, pluginContext), request,
                    null, preImage, userRef);
                break;
            }
#endif

            return(response);
        }
Exemple #7
0
        private void ExecuteIfMatch(Entity workflow, EventOperation operation, ExecutionStage stage,
                                    object entityObject, Entity preImage, Entity postImage, PluginContext pluginContext, Core core)
        {
            // Check if it is supposed to execute. Returns preemptively, if it should not.
            if (workflow.LogicalName != "workflow")
            {
                return;
            }
            var entity    = entityObject as Entity;
            var entityRef = entityObject as EntityReference;

            var guid        = (entity != null) ? entity.Id : entityRef.Id;
            var logicalName = (entity != null) ? entity.LogicalName : entityRef.LogicalName;


            if (workflow.GetAttributeValue <string>("primaryentity") != "" && workflow.GetAttributeValue <string>("primaryentity") != logicalName)
            {
                return;
            }

            if (pluginContext.Depth > 8)
            {
                throw new FaultException(
                          "This workflow job was canceled because the workflow that started it included an infinite loop." +
                          " Correct the workflow logic and try again.");
            }

            var isCreate = operation == EventOperation.Create;
            var isUpdate = operation == EventOperation.Update;
            var isDelete = operation == EventOperation.Delete;

            if (!isCreate && !isUpdate && !isDelete)
            {
                return;
            }

            if (isCreate && (!workflow.GetAttributeValue <bool?>("triggeroncreate").HasValue || !workflow.GetAttributeValue <bool?>("triggeroncreate").Value))
            {
                return;
            }
            if (isDelete && (!workflow.GetAttributeValue <bool?>("triggerondelete").HasValue || !workflow.GetAttributeValue <bool?>("triggerondelete").Value))
            {
                return;
            }
            var triggerFields = new HashSet <string>();

            if (workflow.GetAttributeValue <string>("triggeronupdateattributelist") != null)
            {
                foreach (var field in workflow.GetAttributeValue <string>("triggeronupdateattributelist").Split(','))
                {
                    triggerFields.Add(field);
                }
            }
            if (isUpdate && (
                    workflow.GetAttributeValue <string>("triggeronupdateattributelist") == null ||
                    workflow.GetAttributeValue <string>("triggeronupdateattributelist") == "" ||
                    !entity.Attributes.Any(a => workflow.GetAttributeValue <string>("triggeronupdateattributelist").Split(',').Any(f => a.Key == f))))
            {
                return;
            }

            var thisStage = isCreate ? workflow.GetOptionSetValue <workflow_stage>("createstage") :
                            (isDelete ? workflow.GetOptionSetValue <workflow_stage>("deletestage") : workflow.GetOptionSetValue <workflow_stage>("updatestage"));

            if (thisStage == null)
            {
                thisStage = workflow_stage.Postoperation;
            }

            if ((int)thisStage != (int)stage)
            {
                return;
            }
            // Create the plugin context
            var thisPluginContext = pluginContext.Clone();

            thisPluginContext.Mode              = ((int)workflow.GetOptionSetValue <Workflow_Mode>("mode") + 1) % 2;
            thisPluginContext.Stage             = thisStage.HasValue ? (int)thisStage : (int)workflow_stage.Postoperation;
            thisPluginContext.PrimaryEntityId   = guid;
            thisPluginContext.PrimaryEntityName = logicalName;

            var parsedWorkflow = ParseWorkflow(workflow);

            if (parsedWorkflow == null)
            {
                return;
            }
            WorkflowTree postExecution = null;

            if (thisStage == workflow_stage.Preoperation)
            {
                postExecution = ExecuteWorkflow(parsedWorkflow, preImage, thisPluginContext, core);
            }
            else
            {
                postExecution = ExecuteWorkflow(parsedWorkflow, postImage, thisPluginContext, core);
            }

            if (postExecution.Variables["Wait"] != null)
            {
                waitingWorkflows.Add(postExecution.Variables["Wait"] as WaitInfo);
            }
        }