Command definition object, uses internally SerializableCommandInfo, intended to be one place for all the PowerShell commands definition
Example #1
0
        /// <summary>
        /// Creates command based on the commanf info, reading the calues from attributes
        /// </summary>
        /// <param name="cmdInfo">Command defition</param>
        /// <param name="attributes">Attribute values</param>
        /// <param name="config">Configuration object</param>
        /// <returns>
        /// Ready to execute Command
        /// </returns>
        /// <exception cref="ArgumentNullException">if some of the param is null</exception>
        internal static Command GetCommand(PSExchangeConnector.CommandInfo cmdInfo, ICollection <ConnectorAttribute> attributes, ExchangeConfiguration config)
        {
            Assertions.NullCheck(cmdInfo, "cmdInfo");
            Assertions.NullCheck(attributes, "attributes");

            // create command
            Command cmd = new Command(cmdInfo.Name);

            // map name attribute, if mapping specified
            if (!string.IsNullOrEmpty(cmdInfo.NameParameter))
            {
                object val = GetAttValue(Name.NAME, attributes);
                if (val != null)
                {
                    cmd.Parameters.Add(cmdInfo.NameParameter, val);
                }
            }

            foreach (string attName in cmdInfo.Parameters)
            {
                object val = GetAttValue(attName, attributes);
                if (val == null && attName.Equals("DomainController"))
                {
                    // add domain controller if not provided
                    val = ActiveDirectoryUtils.GetDomainControllerName(config);
                }

                if (val != null)
                {
                    cmd.Parameters.Add(attName, val);
                }
            }

            return(cmd);
        }
Example #2
0
        /// <summary>
        /// Gets the Exchange user using powershell Get-User command
        /// </summary>
        /// <param name="cmdInfo">command info to get the user</param>
        /// <param name="attributes">attributes containing the Name</param>
        /// <returns><see cref="PSObject"/> with user info</returns>
        private PSObject GetUser(ExchangeConnector connector, PSExchangeConnector.CommandInfo cmdInfo, Name nameAttribute)
        {
            ExchangeConfiguration configuration = connector.Configuration;
            // assert we have user name
            string name = nameAttribute.GetNameValue();

            ExchangeUtility.NullCheck(name, "User name", configuration);

            ICollection <ConnectorAttribute> attributes = new List <ConnectorAttribute>();

            attributes.Add(nameAttribute);
            Command cmdUser = ExchangeUtility.GetCommand(cmdInfo, attributes, configuration);
            ICollection <PSObject> users = _helper.InvokePipeline(connector, cmdUser);

            if (users.Count == 1)
            {
                foreach (PSObject obj in users)
                {
                    return(obj);
                }
            }

            throw new ArgumentException(
                      configuration.ConnectorMessages.Format(
                          "ex_bad_username", "Provided User name is not unique or not existing"));
        }
        /// <summary>
        /// Gets the Exchange user using powershell Get-User command
        /// </summary>
        /// <param name="cmdInfo">command info to get the user</param>
        /// <param name="attributes">attributes containing the Name</param>
        /// <returns><see cref="PSObject"/> with user info</returns>
        private PSObject GetUser(PSExchangeConnector.CommandInfo cmdInfo, ICollection <ConnectorAttribute> attributes)
        {
            // assert we have user name
            string name = ExchangeUtility.GetAttValue(Name.NAME, attributes) as string;

            ExchangeUtility.NullCheck(name, "User name", this.configuration);

            Command cmdUser = ExchangeUtility.GetCommand(cmdInfo, attributes, this.configuration);
            ICollection <PSObject> users = this.InvokePipeline(cmdUser);

            if (users.Count == 1)
            {
                foreach (PSObject obj in users)
                {
                    return(obj);
                }
            }

            throw new ArgumentException(
                      this.configuration.ConnectorMessages.Format(
                          "ex_bad_username", "Provided User name is not unique or not existing"));
        }
        /// <summary>
        /// Gets Recipient Type/Database from Exchange database, this method can be more general, but it is ok
        /// for out needs
        /// </summary>
        /// <param name="oc">object class, currently the moethod works for <see cref="ObjectClass.ACCOUNT"/> only</param>
        /// <param name="cobject">connector object to get the recipient type/database for</param>
        /// <param name="attToGet">attributes to get</param>
        /// <returns>Connector Object with recipient type added</returns>
        /// <exception cref="ConnectorException">In case of some troubles in powershell (if the
        /// user is not found we get this exception too)</exception>
        private ConnectorObject AddExchangeAttributes(ObjectClass oc, ConnectorObject cobject, IEnumerable <string> attToGet)
        {
            ExchangeUtility.NullCheck(oc, "name", this.configuration);
            ExchangeUtility.NullCheck(oc, "cobject", this.configuration);

            // we support ACCOUNT only or there is nothing to add
            if (!oc.Is(ObjectClass.ACCOUNT_NAME) || attToGet == null)
            {
                return(cobject);
            }

            // check it is not deleted object
            bool?deleted = ExchangeUtility.GetAttValue(AttIsDeleted, cobject.GetAttributes()) as bool?;

            if (deleted != null && deleted == true)
            {
                // do nothing, it is deleted object
                return(cobject);
            }

            ICollection <string> lattToGet = CollectionUtil.NewCaseInsensitiveSet();

            CollectionUtil.AddAll(lattToGet, attToGet);
            foreach (string att in attToGet)
            {
                if (cobject.GetAttributeByName(att) != null && att != AttDatabase)
                {
                    lattToGet.Remove(att);
                }
            }

            if (lattToGet.Count == 0)
            {
                return(cobject);
            }

            ConnectorObjectBuilder cobjBuilder = new ConnectorObjectBuilder();

            cobjBuilder.AddAttributes(cobject.GetAttributes());

            PSExchangeConnector.CommandInfo cmdInfo = PSExchangeConnector.CommandInfo.GetUser;

            // prepare the connector attribute list to get the command
            ICollection <ConnectorAttribute> attributes = new Collection <ConnectorAttribute> {
                cobject.Name
            };

            // get the command
            Command cmd = ExchangeUtility.GetCommand(cmdInfo, attributes, this.configuration);
            ICollection <PSObject> foundObjects = this.InvokePipeline(cmd);
            PSObject user = null;

            if (foundObjects != null && foundObjects.Count == 1)
            {
                user = GetFirstElement(foundObjects);
                foreach (var info in user.Properties)
                {
                    ConnectorAttribute att = GetAsAttribute(info);
                    if (att != null && lattToGet.Contains(att.Name))
                    {
                        cobjBuilder.AddAttribute(att);
                        lattToGet.Remove(att.Name);
                    }
                }

                if (lattToGet.Count == 0)
                {
                    return(cobjBuilder.Build());
                }
            }

            if (user == null)
            {
                // nothing to do
                return(cobject);
            }

            string rcptType = user.Members[AttRecipientType].Value.ToString();

            foundObjects = null;

            // get detailed information
            if (rcptType == RcptTypeMailBox)
            {
                foundObjects = this.InvokePipeline(ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.GetMailbox, attributes, this.configuration));
            }
            else if (rcptType == RcptTypeMailUser)
            {
                foundObjects = this.InvokePipeline(ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.GetMailUser, attributes, this.configuration));
            }

            if (foundObjects != null && foundObjects.Count == 1)
            {
                PSObject userDetails = GetFirstElement(foundObjects);
                foreach (var info in userDetails.Properties)
                {
                    ConnectorAttribute att = GetAsAttribute(info);
                    if (att != null && lattToGet.Contains(att.Name))
                    {
                        cobjBuilder.AddAttribute(att);
                        lattToGet.Remove(att.Name);
                    }
                }
            }

            return(cobjBuilder.Build());
        }
        /// <summary>
        /// Implementation of UpdateOp.Update
        /// </summary>
        /// <param name="type">Update type</param>
        /// <param name="oclass">Object class</param>
        /// <param name="attributes">Object attributes</param>
        /// <param name="options">Operation options</param>
        /// <returns>Uid of the updated object</returns>
        public override Uid Update(
            UpdateType type,
            ObjectClass oclass,
            ICollection <ConnectorAttribute> attributes,
            OperationOptions options)
        {
            const string METHOD = "Update";

            Debug.WriteLine(METHOD + ":entry", ClassName);

            ExchangeUtility.NullCheck(type, "updatetype", this.configuration);
            ExchangeUtility.NullCheck(oclass, "oclass", this.configuration);
            ExchangeUtility.NullCheck(attributes, "attributes", this.configuration);

            // we handle accounts only
            if (!oclass.Is(ObjectClass.ACCOUNT_NAME))
            {
                return(base.Update(type, oclass, attributes, options));
            }

            // get recipient type and database
            string rcptType = ExchangeUtility.GetAttValue(AttRecipientType, attributes) as string;
            string database = ExchangeUtility.GetAttValue(AttDatabase, attributes) as string;

            // update in AD first
            var filtered = FilterOut(
                attributes,
                PSExchangeConnector.CommandInfo.EnableMailbox,
                PSExchangeConnector.CommandInfo.EnableMailUser,
                PSExchangeConnector.CommandInfo.SetMailbox,
                PSExchangeConnector.CommandInfo.SetMailUser);
            Uid uid = base.Update(type, oclass, filtered, options);

            ConnectorObject aduser = this.ADSearchByUid(uid, oclass, ExchangeUtility.AddAttributeToOptions(options, AttDatabaseADName));

            attributes.Add(aduser.Name);
            PSExchangeConnector.CommandInfo cmdInfo = PSExchangeConnector.CommandInfo.GetUser;
            if (aduser.GetAttributeByName(AttDatabaseADName) != null)
            {
                // we can be sure it is user mailbox type
                cmdInfo = PSExchangeConnector.CommandInfo.GetMailbox;
            }

            PSObject psuser       = this.GetUser(cmdInfo, attributes);
            string   origRcptType = psuser.Members[AttRecipientType].Value.ToString();

            if (String.IsNullOrEmpty(rcptType))
            {
                rcptType = origRcptType;
            }

            if (rcptType == RcptTypeMailUser)
            {
                if (type == UpdateType.REPLACE)
                {
                    if (origRcptType != rcptType)
                    {
                        Command cmdEnable = ExchangeUtility.GetCommand(
                            PSExchangeConnector.CommandInfo.EnableMailUser, attributes, this.configuration);
                        this.InvokePipeline(cmdEnable);
                    }

                    Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetMailUser, attributes, this.configuration);
                    this.InvokePipeline(cmdSet);
                }
                else
                {
                    throw new ConnectorException(this.configuration.ConnectorMessages.Format(
                                                     "ex_wrong_update_type", "Update type [{0}] not supported", type));
                }
            }
            else if (rcptType == RcptTypeMailBox)
            {
                // we should execute something like this here:
                // get-user -identity id|?{$_.RecipientType -eq "User"}|enable-mailbox -database "db"
                // unfortunately I was not able to get it working with the pipeline... that's why there are two commands
                // executed :-(
                // alternatively there can be something like:
                // get-user -identity id -RecipientTypeDetails User|enable-mailbox -database "db", but we have then trouble
                // with detecting attempt to change the database attribute
                string origDatabase = psuser.Members[AttDatabase] != null ? psuser.Members[AttDatabase].Value.ToString() : null;
                if (origRcptType != rcptType)
                {
                    Command cmdEnable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.EnableMailbox, attributes, this.configuration);
                    this.InvokePipeline(cmdEnable);
                }
                else
                {
                    // trying to update the database?
                    if (database != null && database != origDatabase)
                    {
                        throw new ArgumentException(
                                  this.configuration.ConnectorMessages.Format(
                                      "ex_not_updatable", "Update of [{0}] attribute is not supported", AttDatabase));
                    }
                }

                Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetMailbox, attributes, this.configuration);
                this.InvokePipeline(cmdSet);
            }
            else if (rcptType == RcptTypeUser && origRcptType != rcptType)
            {
                throw new ArgumentException(
                          this.configuration.ConnectorMessages.Format(
                              "ex_update_notsupported", "Update of [{0}] to [{1}] is not supported", AttRecipientType, rcptType));
            }
            else if (rcptType != RcptTypeUser)
            {
                // unsupported rcpt type
                throw new ArgumentException(
                          this.configuration.ConnectorMessages.Format(
                              "ex_bad_rcpt", "Recipient type [{0}] is not supported", rcptType));
            }

            Debug.WriteLine(METHOD + ":exit", ClassName);
            return(uid);
        }
        /// <summary>
        /// Implementation of CreateOp.Create
        /// </summary>
        /// <param name="oclass">Object class</param>(oc
        /// <param name="attributes">Object attributes</param>
        /// <param name="options">Operation options</param>
        /// <returns>Uid of the created object</returns>
        public override Uid Create(
            ObjectClass oclass, ICollection <ConnectorAttribute> attributes, OperationOptions options)
        {
            ExchangeUtility.NullCheck(oclass, "oclass", this.configuration);
            ExchangeUtility.NullCheck(attributes, "attributes", this.configuration);

            // we handle accounts only
            if (!oclass.Is(ObjectClass.ACCOUNT_NAME))
            {
                return(base.Create(oclass, attributes, options));
            }

            const string METHOD = "Create";

            Debug.WriteLine(METHOD + ":entry", ClassName);

            // get recipient type
            string rcptType = ExchangeUtility.GetAttValue(AttRecipientType, attributes) as string;

            PSExchangeConnector.CommandInfo cmdInfoEnable = null;
            PSExchangeConnector.CommandInfo cmdInfoSet    = null;
            switch (rcptType)
            {
            case RcptTypeMailBox:
                cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailbox;
                cmdInfoSet    = PSExchangeConnector.CommandInfo.SetMailbox;
                break;

            case RcptTypeMailUser:
                cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailUser;
                cmdInfoSet    = PSExchangeConnector.CommandInfo.SetMailUser;
                break;

            case RcptTypeUser:
                break;

            default:
                throw new ArgumentException(
                          this.configuration.ConnectorMessages.Format(
                              "ex_bad_rcpt", "Recipient type [{0}] is not supported", rcptType));
            }

            // first create the object in AD
            Uid uid = base.Create(oclass, FilterOut(attributes, cmdInfoEnable, cmdInfoSet), options);

            if (rcptType == RcptTypeUser)
            {
                // AD account only, we do nothing
                return(uid);
            }

            // prepare the command
            Command cmdEnable = ExchangeUtility.GetCommand(cmdInfoEnable, attributes, this.configuration);
            Command cmdSet    = ExchangeUtility.GetCommand(cmdInfoSet, attributes, this.configuration);

            try
            {
                this.InvokePipeline(cmdEnable);
                this.InvokePipeline(cmdSet);
            }
            catch
            {
                Trace.TraceWarning("Rolling back AD create for UID: " + uid.GetUidValue());

                // rollback AD create
                try
                {
                    Delete(oclass, uid, options);
                }
                catch
                {
                    Trace.TraceWarning("Not able to rollback AD create for UID: " + uid.GetUidValue());

                    // note: this is not perfect, we hide the original exception
                    throw;
                }

                // rethrow original exception
                throw;
            }

            Debug.WriteLine(METHOD + ":exit", ClassName);
            return(uid);
        }
Example #7
0
        /// <summary>
        /// Creates Exchange 2010 Assembly Resolver, <see cref="ResolveEventHandler"/>
        /// </summary>
        /// <param name="sender">The source of the event</param>
        /// <param name="args">A <see cref="System.ResolveEventArgs"/> that contains the event data</param>
        /// <returns>Assembly resolver that resolves Exchange 2010 assemblies</returns>
//        internal static Assembly AssemblyResolver2010(object sender, ResolveEventArgs args)
//        {
//            // Add path for the Exchange 2010 DLLs
//            if (args.Name.Contains("Microsoft.Exchange"))
//            {
//                string installPath = GetRegistryStringValue(Exchange2010RegKey, ExchangeRegValueName);
//                installPath += "\\bin\\" + args.Name.Split(',')[0] + ".dll";
//                return Assembly.LoadFrom(installPath);
//            }
//
//            return null;
//        }


        /// <summary>
        /// reads the object class info definitions from xml
        /// </summary>
        /// <returns>Dictionary of object classes</returns>
        //internal static IDictionary<ObjectClass, ObjectClassInfo> GetOCInfo()
        //{
        //return CommonUtils.GetOCInfoFromFile(FileObjectClassDef);
        //}

        internal static Command GetCommand(PSExchangeConnector.CommandInfo cmdInfo, ExchangeConfiguration config)
        {
            return(GetCommand(cmdInfo, null, null, null, config));
        }
Example #8
0
        /// <summary>
        /// Creates command based on the commanf info, reading the calues from attributes
        /// </summary>
        /// <param name="cmdInfo">Command defition</param>
        /// <param name="attributes">Attribute values - UID in these is ignored! It should be passed as a separate parameter</param>
        /// <param name="config">Configuration object</param>
        /// <returns>
        /// Ready to execute Command
        /// </returns>
        /// <exception cref="ArgumentNullException">if some of the param is null</exception>
        internal static Command GetCommand(PSExchangeConnector.CommandInfo cmdInfo, ICollection <ConnectorAttribute> attributes, Uid uidAttribute, Name nameAttribute, ExchangeConfiguration config)
        {
            Assertions.NullCheck(cmdInfo, "cmdInfo");

            LOG.Trace("GetCommand: cmdInfo name = {0}", cmdInfo.Name);

            ISet <string> parametersSet = new HashSet <string>();

            // create command
            Command cmd = new Command(cmdInfo.Name);

            if (!string.IsNullOrEmpty(cmdInfo.UidParameter) && !parametersSet.Contains(cmdInfo.UidParameter))
            {
                Uid    uidAttr = uidAttribute != null ? uidAttribute : ConnectorAttributeUtil.GetUidAttribute(attributes);
                string uid     = uidAttr != null?uidAttr.GetUidValue() : null;

                if (uid != null)
                {
                    cmd.Parameters.Add(cmdInfo.UidParameter, ActiveDirectoryUtils.ConvertADGUIDtoObjectGUID(uid));
                    parametersSet.Add(cmdInfo.UidParameter);
                }
            }

            // map name attribute, if mapping specified
            if (!string.IsNullOrEmpty(cmdInfo.NameParameter) && !parametersSet.Contains(cmdInfo.NameParameter))
            {
                Name   nameAttr = nameAttribute != null ? nameAttribute : ConnectorAttributeUtil.GetNameFromAttributes(attributes);
                string name     = nameAttr != null?nameAttr.GetNameValue() : null;;
                if (name != null)
                {
                    cmd.Parameters.Add(cmdInfo.NameParameter, name);
                    parametersSet.Add(cmdInfo.NameParameter);
                }
            }

            if (cmdInfo.UsesConfirm)
            {
                cmd.Parameters.Add("confirm", false);
                parametersSet.Add("confirm");
            }

            if (cmdInfo.UsesDomainController)
            {
                cmd.Parameters.Add("DomainController", ActiveDirectoryUtils.GetDomainControllerName(config));
                parametersSet.Add("DomainController");
            }

            // TODO check this only for user-related operations
            bool emailAddressesPresent     = GetAttValues(ExchangeConnectorAttributes.AttEmailAddresses, attributes) != null;
            bool primarySmtpAddressPresent = GetAttValues(ExchangeConnectorAttributes.AttPrimarySmtpAddress, attributes) != null;

            if (emailAddressesPresent && primarySmtpAddressPresent)
            {
                throw new ArgumentException(ExchangeConnectorAttributes.AttEmailAddresses + " and " + ExchangeConnectorAttributes.AttPrimarySmtpAddress + " cannot be both set.");
            }

            if (attributes != null)
            {
                foreach (string attName in cmdInfo.Parameters)
                {
                    object valueToSet = null;

                    ConnectorAttribute attribute = ConnectorAttributeUtil.Find(attName, attributes);
                    if (attribute != null)
                    {
                        if (attribute.Value != null && attribute.Value.Count > 1)
                        {
                            List <string> stringValues = new List <string>();
                            foreach (object val in attribute.Value)
                            {
                                stringValues.Add(val.ToString());
                            }
                            valueToSet = stringValues.ToArray();
                        }
                        else
                        {
                            valueToSet = ConnectorAttributeUtil.GetSingleValue(attribute);
                        }
                        if (parametersSet.Contains(attName))
                        {
                            throw new InvalidOperationException("Parameter " + attName + " is already defined for command " + cmdInfo.Name);
                        }
                        cmd.Parameters.Add(attName, valueToSet);
                        parametersSet.Add(attName);
                    }
                }
            }

            LOG.Trace("GetCommand exit: cmdInfo name = {0}", cmdInfo.Name);
            return(cmd);
        }
Example #9
0
 internal static Command GetCommand(PSExchangeConnector.CommandInfo cmdInfo, ICollection <ConnectorAttribute> attributes, Uid uidAttribute, ExchangeConfiguration config)
 {
     return(GetCommand(cmdInfo, attributes, uidAttribute, null, config));
 }
Example #10
0
        public void Create(CreateOpContext context)
        {
            context.Attributes = DeduplicateEmailAddresses(context, context.Attributes);

            // get recipient type
            string rcptType = ExchangeUtility.GetAttValue(ExchangeConnectorAttributes.AttRecipientType, context.Attributes) as string;

            if (rcptType == null || rcptType.Equals(""))
            {
                rcptType = ExchangeConnectorAttributes.RcptTypeUser;
            }

            ExchangeConnector        exconn = (ExchangeConnector)context.Connector;
            ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector;

            PSExchangeConnector.CommandInfo cmdInfoEnable = null;
            PSExchangeConnector.CommandInfo cmdInfoSet    = null;
            switch (rcptType)
            {
            case ExchangeConnectorAttributes.RcptTypeMailBox:
                cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailbox;
                cmdInfoSet    = PSExchangeConnector.CommandInfo.SetMailbox;
                break;

            case ExchangeConnectorAttributes.RcptTypeMailUser:
                cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailUser;
                cmdInfoSet    = PSExchangeConnector.CommandInfo.SetMailUser;
                break;

            case ExchangeConnectorAttributes.RcptTypeUser:
                break;

            default:
                throw new ArgumentException(
                          context.ConnectorConfiguration.ConnectorMessages.Format(
                              "ex_bad_rcpt", "Recipient type [{0}] is not supported", rcptType));
            }

            // first create the object in AD
            ICollection <ConnectorAttribute> adAttributes = ExchangeUtility.FilterOut(context.Attributes,
                                                                                      PSExchangeConnector.CommandInfo.EnableMailbox,
                                                                                      PSExchangeConnector.CommandInfo.SetMailbox,
                                                                                      PSExchangeConnector.CommandInfo.EnableMailUser,
                                                                                      PSExchangeConnector.CommandInfo.SetMailUser);
            Uid uid = adconn.Create(context.ObjectClass, adAttributes, context.Options);

            if (rcptType == ExchangeConnectorAttributes.RcptTypeUser)
            {
                // AD account only, we do nothing
                context.Uid = uid;
                return;
            }

            // add a empty "EmailAddresses" attribute if needed (address policy is disabled and no addresses are provided)
            ICollection <ConnectorAttribute> enhancedAttributes;
            ConnectorAttribute policyEnabledAttribute = ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddressPolicyEnabled, context.Attributes);

            if (policyEnabledAttribute != null &&
                ConnectorAttributeUtil.GetBooleanValue(policyEnabledAttribute).HasValue&&
                ConnectorAttributeUtil.GetBooleanValue(policyEnabledAttribute).Value == false &&
                ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttPrimarySmtpAddress, context.Attributes) == null &&
                ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddresses, context.Attributes) == null)
            {
                enhancedAttributes = new HashSet <ConnectorAttribute>(context.Attributes);
                enhancedAttributes.Add(ConnectorAttributeBuilder.Build(ExchangeConnectorAttributes.AttEmailAddresses));
                LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Added empty EmailAddresses attribute because address policy use is disabled and no addresses were provided");
            }
            else
            {
                enhancedAttributes = context.Attributes;        // no change
            }

            // prepare the command
            Command cmdEnable = ExchangeUtility.GetCommand(cmdInfoEnable, enhancedAttributes, uid, (ExchangeConfiguration)context.ConnectorConfiguration);
            Command cmdSet    = ExchangeUtility.GetCommand(cmdInfoSet, enhancedAttributes, uid, (ExchangeConfiguration)context.ConnectorConfiguration);

            try {
                _helper.InvokePipeline(exconn, cmdEnable);
                _helper.InvokePipeline(exconn, cmdSet);
            }
            catch {
                LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Rolling back AD create for UID: " + uid.GetUidValue());

                // rollback AD create
                try {
                    adconn.Delete(context.ObjectClass, uid, context.Options);
                } catch {
                    LOGGER.TraceEvent(TraceEventType.Warning, CAT_DEFAULT, "Not able to rollback AD create for UID: " + uid.GetUidValue());
                    // note: this is not perfect, we hide the original exception
                    throw;
                }

                // rethrow original exception
                throw;
            }

            context.Uid = uid;
        }