コード例 #1
0
        protected override void Initialize(IServiceProvider provider)
        {
            SequentialWorkflow containingSequentialWorkflow = null;

            SequentialWorkflow.TryGetContainingWorkflow(this, out containingSequentialWorkflow);

            //using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
            //{
            //    using (DefaultClient client = new DefaultClient())
            //    {
            //        client.RefreshSchema();


            //        Guid targetUser;
            //        if (containingSequentialWorkflow.ActorId == CellOTPGate.AnonymousID)
            //        { targetUser = containingSequentialWorkflow.TargetId; }
            //        else
            //        { targetUser = containingSequentialWorkflow.ActorId; }

            //        RmPerson person = client.Get(new Microsoft.ResourceManagement.ObjectModel.RmReference(targetUser.ToString())) as RmPerson;
            //        userCellPhone = person.MobilePhone;
            //    }
            //}

            base.Initialize(provider);
        }
コード例 #2
0
        /// <summary>
        /// Copy the FIM WorkflowData items to a Dictionary
        /// </summary>
        /// <param name="variablesInputString">the String containing the WorkflowData item name(s)</param>
        /// <returns>a Dictionary containing WorkflowData.Name WorkflowData.Value</returns>
        private Dictionary <String, Object> PowerShellSessionVariables(String variablesInputString)
        {
            Dictionary <String, Object> powerShellSessionVariables = new Dictionary <String, Object>();

            // In order to read the Workflow Dictionary we need to get the containing (parent) workflow
            SequentialWorkflow containingWorkflow = null;

            if (!SequentialWorkflow.TryGetContainingWorkflow(this, out containingWorkflow))
            {
                throw new InvalidOperationException("Unable to get Containing Workflow");
            }

            String logOutput = "Containing Workflow Dictionary (WorkflowData):";

            foreach (String workflowDataName in variablesInputString.Split(new Char[] { ' ', ',', '.', ':', ';' }))
            {
                try
                {
                    String workflowDataValue = containingWorkflow.WorkflowDictionary[workflowDataName].ToString();
                    powerShellSessionVariables.Add(workflowDataName, workflowDataValue);
                    logOutput += String.Format("\n\t{0}: {1}", workflowDataName, workflowDataValue);
                }
                catch (KeyNotFoundException keyNotFoundException)
                {
                    trace.TraceFatal("Required item missing from FIM Workflow Data.\n", keyNotFoundException.StackTrace);
                    throw new KeyNotFoundException("Required item missing from FIM Workflow Data.", keyNotFoundException.InnerException);
                }
            }
            trace.TraceVerbose(logOutput);

            return(powerShellSessionVariables);
        }
コード例 #3
0
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            SequentialWorkflow containingSequentialWorkflow = null;

            SequentialWorkflow.TryGetContainingWorkflow(this, out containingSequentialWorkflow);

            this.readResourceActivity1.ActorId    = new Guid("e05d1f1b-3d5e-4014-baa6-94dee7d68c89");
            this.readResourceActivity1.ResourceId = containingSequentialWorkflow.TargetId;
            return(base.Execute(executionContext));
        }
コード例 #4
0
        /// <summary>
        /// Handles the ExecuteCode event of the PrepareDelete CodeActivity.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void PrepareDelete_ExecuteCode(object sender, EventArgs e)
        {
            Logger.Instance.WriteMethodEntry(EventIdentifier.DeleteResourcesPrepareDeleteExecuteCode, "TargetType: '{0}'.", this.TargetType);

            try
            {
                // Determine the resources to be deleted based on the target type
                switch (this.TargetType)
                {
                case DeleteResourcesTargetType.WorkflowTarget:
                    // If the activity is configured to delete the workflow target,
                    // load the target from the parent workflow
                    SequentialWorkflow parentWorkflow;
                    if (SequentialWorkflow.TryGetContainingWorkflow(this, out parentWorkflow))
                    {
                        this.Targets.Add(parentWorkflow.TargetId);
                    }

                    break;

                case DeleteResourcesTargetType.SearchForTarget:
                    // If the activity is configured to search for the target(s),
                    // the targets should be the bound results of the find resources activity
                    break;

                case DeleteResourcesTargetType.ResolveTarget:
                    // If the activity is configured to resolve target(s),
                    // verify that the supplied lookup resolved to a Guid or List<Guid> and assign the resolved
                    // values as targets
                    if (this.Resolve.Lookups.ContainsKey(this.TargetExpression) &&
                        this.Resolve.Lookups[this.TargetExpression] != null)
                    {
                        if (this.Resolve.Lookups[this.TargetExpression] is Guid)
                        {
                            this.Targets.Add((Guid)this.Resolve.Lookups[this.TargetExpression]);
                        }
                        else if (this.Resolve.Lookups[this.TargetExpression].GetType() == typeof(List <Guid>))
                        {
                            this.Targets = (List <Guid>) this.Resolve.Lookups[this.TargetExpression];
                        }
                    }

                    break;
                }
            }
            finally
            {
                Logger.Instance.WriteMethodExit(EventIdentifier.DeleteResourcesPrepareDeleteExecuteCode, "TargetType: '{0}'. Target Count: {1}.", this.TargetType, this.Targets.Count);
            }
        }
コード例 #5
0
        /// <summary>
        /// Executes the activity.
        /// </summary>
        /// <param name="executionContext">The execution context.</param>
        /// <returns>The <see cref="ActivityExecutionStatus"/> object.</returns>
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            Logger.Instance.WriteMethodEntry(EventIdentifier.AsyncUpdateResourceExecute);

            try
            {
                // Ideally we would set CallContext in OnActivityExecutionContextLoad instead here in Execute
                // as OnActivityExecutionContextLoad gets called on each hydration and rehydration of the workflow instance
                // but looks like it's invoked on a different thread context than the rest of the workflow instance execution.
                // To minimize the loss of the CallContext on rehydration, we'll set it in the Execute of every WAL child activities.
                // It will still get lost (momentarily) when the workflow is persisted in the middle of the execution of a replicator activity, for example.
                Logger.SetContextItem(this, this.WorkflowInstanceId);

                SequentialWorkflow parentWorkflow;
                if (!SequentialWorkflow.TryGetContainingWorkflow(this, out parentWorkflow))
                {
                    throw Logger.Instance.ReportError(new InvalidOperationException(Messages.UnableToGetParentWorkflowError));
                }

                // Create the workflow program queue so we can facilitate asynchronous
                // submission of requests
                WorkflowQueue queue = CreateWorkflowProgramQueue(this.queuingService, this);

                object[] args = new object[] { this.ActorId, this.ResourceId, this.UpdateParameters, parentWorkflow.RequestId, this.ApplyAuthorizationPolicy, 0, queue.QueueName };

                Logger.Instance.WriteVerbose(EventIdentifier.AsyncUpdateResourceExecute, "Invoking DataAccessService.Update() for ActorId: '{0}', ResourceId: '{1}', ParentRequestId: '{3}' ApplyAuthorizationPolicy: '{4}' and QueueName: '{6}'.", args);

                // Submit the request via reflection and cleanup the queue
                // Added the AuthorizationTimeOut value of 0, which is "Fire and Forget"
                this.dataAccessServiceType.InvokeMember(
                    "Update",
                    BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
                    null,
                    this.dataAccessService,
                    args,
                    CultureInfo.InvariantCulture);

                DeleteWorkflowProgramQueue(this.queuingService, queue);

                return(base.Execute(executionContext));
            }
            catch (Exception ex)
            {
                throw Logger.Instance.ReportError(EventIdentifier.AsyncUpdateResourceExecuteError, ex);
            }
            finally
            {
                Logger.Instance.WriteMethodExit(EventIdentifier.AsyncUpdateResourceExecute);
            }
        }
コード例 #6
0
ファイル: Logger.cs プロジェクト: titus-studios-media/MIMWAL
        public static void SetContextItem(Activity activity, Guid workflowInstanceId)
        {
            Logger.SetContextItem("WorkflowInstanceId", workflowInstanceId);

            SequentialWorkflow parentWorkflow;

            if (!SequentialWorkflow.TryGetContainingWorkflow(activity, out parentWorkflow))
            {
                return;
            }

            Logger.SetContextItem("RequestId", parentWorkflow.RequestId);
            Logger.SetContextItem("ActorId", parentWorkflow.ActorId);
            Logger.SetContextItem("TargetId", parentWorkflow.TargetId);
            Logger.SetContextItem("WorkflowDefinitionId", parentWorkflow.WorkflowDefinitionId);
        }
        private void InitializeUpdate_ExecuteCode(object sender, EventArgs e)
        {
            if (readResourceActivity1.Resource["labSource"].ToString() == "INTERNAL")
            {
                if (countUpn <= 1)
                {
                    displayName = firstName + " " + lastName;
                }
                else
                {
                    displayName = firstName + " " + lastName + countUpn.ToString();
                }
            }
            else
            {
                if (countUpn <= 1)
                {
                    displayName = firstName + " " + lastName + ",EX";
                }
                else
                {
                    displayName = firstName + " " + lastName + countUpn.ToString() + ",EX";
                }
            }

            //Get containing Workflow
            SequentialWorkflow containingWorkflow = null;

            if (!SequentialWorkflow.TryGetContainingWorkflow(this, out containingWorkflow))
            {
                throw new InvalidOperationException("Could not get parent workflow!");
            }

            string displayNameSuffix = ReadWorkFlowParameters(UpnSuffix, containingWorkflow);

            displayName += displayNameSuffix;

            updateResourceActivity1_ActorId1         = requestorGUID;
            updateResourceActivity1_ResourceId1      = targetGUID;
            updateResourceActivity1.UpdateParameters = new UpdateRequestParameter[] {
                new UpdateRequestParameter("AccountName", UpdateMode.Modify, samAccountName),
                new UpdateRequestParameter("DisplayName", UpdateMode.Modify, displayName),
                new UpdateRequestParameter("labUpn", UpdateMode.Modify, upn)
            };
        }
        private void InitiliazeReadSubject_ExecuteCode(object sender, EventArgs e)
        {
            RequestType currentRequest = this.ReadCurrentRequestActivity.CurrentRequest;
            ReadOnlyCollection <CreateRequestParameter> requestParameters = currentRequest.ParseParameters <CreateRequestParameter>();

            SequentialWorkflow containingWorkflow = null;

            if (!SequentialWorkflow.TryGetContainingWorkflow(this, out containingWorkflow))
            {
                throw new InvalidOperationException("Unable to get Containing Workflow");
            }

            this.readResourceActivity1_ActorId1    = FIMADMGUID;
            this.readResourceActivity1_ResourceId1 = containingWorkflow.TargetId;

            requestorGUID = containingWorkflow.ActorId;
            targetGUID    = containingWorkflow.TargetId;
        }
コード例 #9
0
        private void initializeReadCostCenter_ExecuteCode(object sender, EventArgs e)
        {
            RequestType currentRequest = this.ReadCurrentRequest.CurrentRequest;
            ReadOnlyCollection <CreateRequestParameter> requestParameters = currentRequest.ParseParameters <CreateRequestParameter>();

            // Retrieve current workflow
            SequentialWorkflow workflow = null;

            if (!SequentialWorkflow.TryGetContainingWorkflow(this, out workflow))
            {
                throw new InvalidOperationException();
            }

            // Save information
            _requestor = workflow.ActorId;
            _target    = workflow.TargetId;

            // Init ReadUser activity
            this.ReadCostCenter_ActorId1    = FIMADMGUID;
            this.ReadCostCenter_ResourceId1 = _target;
        }
コード例 #10
0
        /// <summary>
        /// Handles the ExecuteCode event of the Prepare CodeActivity.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void Prepare_ExecuteCode(object sender, EventArgs e)
        {
            Logger.Instance.WriteMethodEntry(EventIdentifier.FindResourcesPrepareExecuteCode);

            try
            {
                // Prepare the output lists
                this.FoundResources = new List <ResourceType>();
                this.FoundIds       = new List <Guid>();

                // Retrieve the target resource for the workflow
                SequentialWorkflow parentWorkflow;
                if (SequentialWorkflow.TryGetContainingWorkflow(this, out parentWorkflow))
                {
                    this.workflowTarget = parentWorkflow.TargetId;
                }

                // Throw an exception if the XPath filter was not supplied for the activity
                if (string.IsNullOrEmpty(this.XPathFilter))
                {
                    throw Logger.Instance.ReportError(EventIdentifier.FindResourcesPrepareExecuteCodeMissingXPathError, new InvalidOperationException(Messages.FindResources_MissingXPathError));
                }

                // Configure the selection attributes for the Enumerate Resources activity
                // If attributes were not supplied for the activity, default to just the ObjectID to reduce the overhead
                // associated with retrieving all attributes for enumerated resources
                if (this.Attributes != null && this.Attributes.Length > 0)
                {
                    this.Find.Selection = this.Attributes;
                }
                else
                {
                    this.Find.Selection = new string[] { "ObjectID" };
                }
            }
            finally
            {
                Logger.Instance.WriteMethodExit(EventIdentifier.FindResourcesPrepareExecuteCode, "XPathFilter to Resolve: '{0}'. Attributes to Read: '{1}'.", this.XPathFilter, string.Join(",", this.Find.Selection));
            }
        }
コード例 #11
0
        protected override void InitializeAuthenticationGate(IServiceProvider provider)
        {
            sentSMS = false;

            // When the activity is first loaded, we're going to try to retrieve the user info from the registration data
            if (this.AuthenticationGateActivity.RegistrationData == null ||
                string.IsNullOrEmpty(this.userCellPhone = UnicodeEncoding.Unicode.GetString(this.AuthenticationGateActivity.RegistrationData)))
            {
                //Looks like our cell phone data was not stored in registration data
                //Default to FIM store
                using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
                {
                    using (DefaultClient client = new DefaultClient())
                    {
                        client.RefreshSchema();

                        SequentialWorkflow containingSequentialWorkflow = null;
                        SequentialWorkflow.TryGetContainingWorkflow(this.AuthenticationGateActivity, out containingSequentialWorkflow);

                        Guid targetUser;
                        if (containingSequentialWorkflow.ActorId == CellOTPGate.AnonymousID)
                        {
                            targetUser = containingSequentialWorkflow.TargetId;
                        }
                        else
                        {
                            targetUser = containingSequentialWorkflow.ActorId;
                        }

                        RmPerson person = client.Get(new Microsoft.ResourceManagement.ObjectModel.RmReference(targetUser.ToString())) as RmPerson;
                        this.userCellPhone = person.MobilePhone;
                    }
                }
            }

            base.InitializeAuthenticationGate(provider);
        }
コード例 #12
0
        private void Decide_ExecuteCode(object sender, EventArgs e)
        {
            Logger.Instance.WriteMethodEntry(EventIdentifier.DetermineActorDecideExecuteCode, "ActorType: '{0}'.", this.ActorType);

            try
            {
                switch (this.ActorType)
                {
                case ActorType.Service:
                    this.Actor = WellKnownGuids.FIMServiceAccount;
                    break;

                case ActorType.Requestor:
                    SequentialWorkflow parentWorkflow;
                    SequentialWorkflow.TryGetContainingWorkflow(this, out parentWorkflow);
                    this.Actor = parentWorkflow.ActorId;
                    break;

                case ActorType.Resolve:
                    object resolved = this.ActivityExpressionEvaluator.ResolveExpression(this.ActorString);
                    if (resolved is Guid)
                    {
                        this.Actor = (Guid)resolved;
                    }
                    else if (resolved == null)
                    {
                        throw Logger.Instance.ReportError(new WorkflowActivityLibraryException(Messages.DetermineActor_NullResolvedActorError));
                    }
                    else if (resolved.GetType().IsGenericType&& resolved.GetType().GetGenericTypeDefinition() == typeof(List <>))
                    {
                        throw Logger.Instance.ReportError(new WorkflowActivityLibraryException(Messages.DetermineActor_MultipleResolvedActorsError));
                    }
                    else if (resolved is string && !string.IsNullOrEmpty(resolved as string))
                    {
                        try
                        {
                            this.Actor = new Guid(resolved as string);
                        }
                        catch (Exception ex)
                        {
                            throw Logger.Instance.ReportError(new WorkflowActivityLibraryException(Messages.DetermineActor_InvalidActorGuidFormatError, ex));
                        }
                    }
                    else
                    {
                        throw Logger.Instance.ReportError(new WorkflowActivityLibraryException(Messages.DetermineActor_UnresolvedActorError));
                    }

                    break;

                case ActorType.Account:
                    switch (this.Query.FoundIds.Count)
                    {
                    case 1:
                        this.Actor = this.Query.FoundIds[0];
                        break;

                    case 0:
                        throw Logger.Instance.ReportError(EventIdentifier.DetermineActorDecideExecuteCodeNotFoundActorAccountError, new WorkflowActivityLibraryException(Messages.DetermineActor_NotFoundActorAccountError));

                    default:
                        throw Logger.Instance.ReportError(EventIdentifier.DetermineActorDecideExecuteCodeMultipleActorAccountsError, new WorkflowActivityLibraryException(Messages.DetermineActor_MultipleActorAccountsError));
                    }

                    break;
                }
            }
            finally
            {
                Logger.Instance.WriteMethodExit(EventIdentifier.DetermineActorDecideExecuteCode, "ActorType: '{0}'. Actor: '{1}'. ", this.ActorType, this.Actor);
            }
        }
コード例 #13
0
        /// <summary>
        /// Runs the PowerShell Script using:
        ///  - FIM WorkflowData items as PowerShell variables
        ///  - the specified PowerShell module (if specified in the WF)
        ///  - stores the script output in a new FIM WorkflowData item (if specified in the WF)
        /// </summary>
        private void RunScript()
        {
            trace.TraceStart("START PowerShellActivity RunScript");

            ///
            /// Translate the WorkflowData items to PowerShell variables
            ///
            InitialSessionState initialSessionState = InitialSessionState.CreateDefault();
            String logDetailForPowerShellVariables  = string.Empty;

            if (!String.IsNullOrEmpty(this.PowerShellVariables))
            {
                logDetailForPowerShellVariables = "### PowerShell Variables from FIM WorkflowData";

                foreach (KeyValuePair <String, Object> sessionVariable in this.PowerShellSessionVariables(PowerShellVariables))
                {
                    trace.TraceVerbose("Adding PowerShell Session Variable:\n{0} : {1}", sessionVariable.Key, sessionVariable.Value);
                    initialSessionState.Variables.Add(new SessionStateVariableEntry(sessionVariable.Key, sessionVariable.Value, null));
                    logDetailForPowerShellVariables += String.Format("\n${0} = '{1}'", sessionVariable.Key, sessionVariable.Value);
                }
            }

            ///
            /// Load the PowerShell Module if specified by the WF
            ///
            if (!String.IsNullOrEmpty(this.PowerShellModule))
            {
                trace.TraceInformation("Loading PowerShell Module: {0}", this.PowerShellModule);
                initialSessionState.ImportPSModule(new String[] { PowerShellModule });
            }

            // Call the RunspaceFactory.CreateRunspace(InitialSessionState)
            // method to create the runspace where the pipeline is run.
            Runspace runspace = RunspaceFactory.CreateRunspace(initialSessionState);

            runspace.Open();

            using (PowerShell powershell = PowerShell.Create())
            {
                powershell.Runspace = runspace;
                powershell.AddScript(Script);
                powershell.AddParameter("Verbose");

                // Invoke the PowerShell Pipeline synchronously
                trace.TraceInformation("### Invoking Pipeline\n{0}\n\n###PowerShell Script from WF\n{1}", logDetailForPowerShellVariables, Script);
                try
                {
                    Collection <PSObject> results = powershell.Invoke();

                    // Display the results.
                    trace.TraceVerbose("{0} results returned.", results.Count);
                    foreach (PSObject result in results)
                    {
                        String psObjectDetail = result.ToString();
                        //foreach (PSMemberInfo member in result.Members)
                        //{
                        //    psObjectDetail += String.Format("\n\t{0}:{1}", member.Name, member.Value);
                        //}
                        foreach (PSMemberInfo member in result.Properties)
                        {
                            psObjectDetail += String.Format("\n\t{0}:{1}", member.Name, member.Value);
                        }
                        trace.TraceVerbose(psObjectDetail);
                    }
                    // Throw on any non-terminating errors.
                    foreach (ErrorRecord error in powershell.Streams.Error)
                    {
                        trace.TraceWarning("PowerShell Error: {0}", error);
                        String errorText = String.Format("PowerShell activity failed with the following error: \n{0}", error.ToString());
                        throw new Microsoft.ResourceManagement.Workflow.WorkflowExtensionException("PowerShell Activity", errorText);
                    }

                    ///
                    /// Copy the PowerShell output to the FIM WorkflowData dictionary
                    ///
                    if (results.Count == 1 & !String.IsNullOrEmpty(this.WorkflowDataNameForOutput))
                    {
                        trace.TraceVerbose("Storing the PowerShell output in FIM WorkflowData item named: {0}", this.WorkflowDataNameForOutput);
                        // In order to add our PowerShell result to the FIM Workflow Dictionary we need to get the containing (parent) workflow
                        SequentialWorkflow containingWorkflow = null;
                        if (!SequentialWorkflow.TryGetContainingWorkflow(this, out containingWorkflow))
                        {
                            trace.TraceError("Unable to get Containing Workflow.");
                            throw new InvalidOperationException("Unable to get Containing Workflow");
                        }
                        containingWorkflow.WorkflowDictionary[this.WorkflowDataNameForOutput] = results[0].ToString();
                    }
                }
                catch (RuntimeException ex)
                {
                    trace.TraceError("PowerShell Error: {0}", ex.Message);
                    throw;
                }
                finally
                {
                    // Throw on any non-terminating errors.
                    String verboseOutput = "PowerShell Verbose Output:\n";
                    foreach (VerboseRecord verboseRecord in powershell.Streams.Verbose)
                    {
                        verboseOutput += verboseRecord.ToString();
                    }
                    trace.TraceVerbose(verboseOutput);
                }
            }

            trace.TraceStop("STOP PowerShellActivity RunScript");
        }
コード例 #14
0
        /// <summary>
        /// Handles the ExecuteCode event of the BuildRequests CodeActivity.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void BuildRequests_ExecuteCode(object sender, EventArgs e)
        {
            Logger.Instance.WriteMethodEntry(EventIdentifier.UpdateLookupsBuildRequestsExecuteCode);

            try
            {
                foreach (UpdateLookupDefinition update in this.UpdateLookupDefinitions)
                {
                    LookupEvaluator lookup = new LookupEvaluator(update.TargetLookup);
                    if (lookup.TargetIsWorkflowDictionary)
                    {
                        // Get the parent workflow to facilitate access to the workflow dictionary
                        SequentialWorkflow parentWorkflow;
                        SequentialWorkflow.TryGetContainingWorkflow(this, out parentWorkflow);

                        // For simplicity, start by adding the key to the parent workflow dictionary so we can assume that its there
                        if (!parentWorkflow.WorkflowDictionary.ContainsKey(lookup.TargetAttribute))
                        {
                            parentWorkflow.WorkflowDictionary.Add(lookup.TargetAttribute, null);
                        }

                        if (update.Mode == UpdateMode.Modify)
                        {
                            parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] = update.Value;
                        }
                        else if (update.Value != null)
                        {
                            // Use reflection to determine the expected List<> type based on the value
                            // Also get the Add and Remove methods for the list
                            Type       listType = typeof(List <>).MakeGenericType(new Type[] { update.Value.GetType() });
                            MethodInfo add      = listType.GetMethod("Add");
                            MethodInfo remove   = listType.GetMethod("Remove");

                            switch (update.Mode)
                            {
                            case UpdateMode.Insert:
                                if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] == null)
                                {
                                    parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] = update.Value;
                                }
                                else if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute].GetType() == update.Value.GetType())
                                {
                                    // Single value, create a new instance of the appropriate List<> type
                                    // and add both values: existing and new
                                    object existingValue = parentWorkflow.WorkflowDictionary[lookup.TargetAttribute];
                                    parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] = Activator.CreateInstance(listType);
                                    add.Invoke(parentWorkflow.WorkflowDictionary[lookup.TargetAttribute], new object[] { existingValue });
                                    add.Invoke(parentWorkflow.WorkflowDictionary[lookup.TargetAttribute], new object[] { update.Value });
                                }
                                else if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute].GetType() == listType)
                                {
                                    // The dictionary key is a list of the expected type, add the value
                                    add.Invoke(parentWorkflow.WorkflowDictionary[lookup.TargetAttribute], new object[] { update.Value });
                                }
                                else
                                {
                                    // We have a problem and need to report an error
                                    throw Logger.Instance.ReportError(new WorkflowActivityLibraryException(Messages.UpdateLookup_InsertVariableError, update.Value.GetType(), lookup.TargetAttribute, parentWorkflow.WorkflowDictionary[lookup.TargetAttribute].GetType()));
                                }

                                break;

                            case UpdateMode.Remove:
                                if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] == null)
                                {
                                    // Do nothing
                                }
                                else if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute].Equals(update.Value))
                                {
                                    // A single matching value exists, clear the variable
                                    parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] = null;
                                }
                                else if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute].GetType() == listType)
                                {
                                    // The variable is a list of the expected type, attempt to remove the value
                                    remove.Invoke(parentWorkflow.WorkflowDictionary[lookup.TargetAttribute], new object[] { update.Value });

                                    // Check the count on the list to determine if we are down to a single value or have no value
                                    // If so, adjust the value of the variable accordingly to eliminate the list
                                    object listValue = null;
                                    int    i         = 0;
                                    foreach (object o in (IEnumerable)parentWorkflow.WorkflowDictionary[lookup.TargetAttribute])
                                    {
                                        i        += 1;
                                        listValue = o;
                                    }

                                    if (i <= 1)
                                    {
                                        parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] = listValue;
                                    }
                                }

                                break;
                            }
                        }

                        // If we ended up with a null value in the workflow dictionary key,
                        // remove the key to cleanup after ourselves
                        if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] == null)
                        {
                            parentWorkflow.WorkflowDictionary.Remove(lookup.TargetAttribute);
                        }
                    }
                    else if (!string.IsNullOrEmpty(lookup.TargetResourceLookup) &&
                             this.TargetLookups.ContainsKey(lookup.TargetResourceLookup) &&
                             this.TargetLookups[lookup.TargetResourceLookup] != null)
                    {
                        // Based on the type of the resolved target lookup (should be Guid or List<Guid>)
                        // build the list of target resources for the update
                        List <Guid> targets = new List <Guid>();
                        if (this.TargetLookups[lookup.TargetResourceLookup] is Guid)
                        {
                            targets.Add((Guid)this.TargetLookups[lookup.TargetResourceLookup]);
                        }
                        else if (this.TargetLookups[lookup.TargetResourceLookup].GetType() == typeof(List <Guid>))
                        {
                            targets.AddRange((List <Guid>) this.TargetLookups[lookup.TargetResourceLookup]);
                        }

                        foreach (Guid target in targets)
                        {
                            // Add the target to the update requests dictionary, if it doesn't already exist,
                            // and add the new update request parameter
                            if (!this.PendingRequests.ContainsKey(target))
                            {
                                this.PendingRequests.Add(target, new List <UpdateRequestParameter>());
                            }

                            this.PendingRequests[target].Add(new UpdateRequestParameter(lookup.TargetAttribute, update.Mode, update.Value));
                        }
                    }
                }

                // If there are requests that need to be submitted to fulfill the updates,
                // assign the list of targets to the for each loop which will evaluate each change
                // to determine if they will result in changes
                if (this.PendingRequests.Count > 0)
                {
                    this.ForEachPending.InitialChildData = this.PendingRequests.Keys.ToList();
                }

                Logger.Instance.WriteVerbose(EventIdentifier.UpdateLookupsBuildRequestsExecuteCode, "The number of requests that need to be submitted to fulfill the updates: '{0}'.", this.PendingRequests.Count);
            }
            finally
            {
                Logger.Instance.WriteMethodExit(EventIdentifier.UpdateLookupsBuildRequestsExecuteCode);
            }
        }