/// <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")); }
// TODO move to appropriate place /// <summary> /// helper method for searching object in AD by UID /// </summary> /// <param name="uid">Uid of the searched </param> /// <param name="oclass">Object class</param> /// <param name="options">Operation options</param> /// <returns>Connector object found by the Uid</returns> internal ConnectorObject ADSearchByUid(ExchangeConnector connector, Uid uid, ObjectClass oclass, OperationOptions options) { ExchangeConfiguration configuration = connector.Configuration; ExchangeUtility.NullCheck(uid, "uid", configuration); ExchangeUtility.NullCheck(oclass, "oclass", configuration); if (options == null) { options = new OperationOptionsBuilder().Build(); } ConnectorObject ret = null; Filter filter = FilterBuilder.EqualTo(uid); var translator = connector.ActiveDirectoryConnector.CreateFilterTranslator(oclass, options); IList <string> queries = translator.Translate(filter); if (queries.Count == 1) { ResultsHandler handler = new ResultsHandler() { Handle = cobject => { ret = cobject; return(false); } }; connector.ActiveDirectoryConnector.ExecuteQuery(oclass, queries[0], handler, options); } return(ret); }
/// <summary> /// helper method for searching object in AD by UID /// </summary> /// <param name="uid">Uid of the searched </param> /// <param name="oclass">Object class</param> /// <param name="options">Operation options</param> /// <returns>Connector object found by the Uid</returns> private ConnectorObject ADSearchByUid(Uid uid, ObjectClass oclass, OperationOptions options) { ExchangeUtility.NullCheck(uid, "uid", this.configuration); ExchangeUtility.NullCheck(oclass, "oclass", this.configuration); if (options == null) { options = new OperationOptionsBuilder().Build(); } ConnectorObject ret = null; Filter filter = FilterBuilder.EqualTo(uid); var translator = base.CreateFilterTranslator(oclass, options); IList <string> queries = translator.Translate(filter); if (queries.Count == 1) { ResultsHandler handler = delegate(ConnectorObject cobject) { ret = cobject; return(false); }; base.ExecuteQuery(oclass, queries[0], handler, options); } return(ret); }
public void ExecuteQuery(ExecuteQueryContext context) { ExchangeConnector exconn = (ExchangeConnector)context.Connector; LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "SimplePowerShellObjectHandler: Executing query: query={0}", context.Query); Command cmdGet = ExchangeUtility.GetCommand( new PSExchangeConnector.CommandInfo(GetGetCommandName()), exconn.Configuration); if (context.Query != null) { cmdGet.Parameters.Add("Identity", context.Query); } ICollection <PSObject> objects; try { objects = _helper.InvokePipeline(exconn, cmdGet); } catch (ObjectNotFoundException e) { LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "SimplePowerShellObjectHandler: Executing query: got 'ObjectNotFound' exception ({0}), assuming suitable objects do not exist", e); return; } LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "SimplePowerShellObjectHandler: Executing query: got {0} objects", objects.Count); foreach (PSObject psobject in objects) { if (psobject != null) { context.ResultsHandler.Handle(_helper.CreateConnectorObject(exconn, psobject, context.ObjectClass)); } } }
/// <summary> /// Implementation of SynOp.Sync /// </summary> /// <param name="objClass">Object class</param> /// <param name="token">Sync token</param> /// <param name="handler">Sync results handler</param> /// <param name="options">Operation options</param> public void Sync( ObjectClass oclass, SyncToken token, SyncResultsHandler handler, OperationOptions options) { const string operation = "Sync"; ExchangeUtility.NullCheck(oclass, "oclass", this._configuration); LOG.Info("Exchange.Sync method; oclass = {0}, token = {1}", oclass, token); SyncOpContext context = new SyncOpContext() { Connector = this, ConnectorConfiguration = _configuration, ObjectClass = oclass, OperationName = operation, Options = options, SyncToken = token, SyncResultsHandler = handler }; try { _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain); if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain)) { SyncMain(context); } _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain); } catch (Exception e) { LOG.Error(e, "Exception while executing Sync operation: {0}"); throw; } // TODO what about executing a script on each returned item? }
public void Delete(ObjectClass objClass, Uid uid, OperationOptions options) { const string operation = "Delete"; plugins.OnBeforeDelete(objClass, uid, options, _configuration); ExchangeUtility.NullCheck(objClass, "objClass", this._configuration); ExchangeUtility.NullCheck(uid, "uid", this._configuration); LOG.Info("Exchange.Delete method; uid:\n{0}", uid.GetUidValue()); DeleteOpContext context = new DeleteOpContext() { Connector = this, ConnectorConfiguration = _configuration, ObjectClass = objClass, OperationName = operation, Uid = uid, Options = options }; try { _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain); if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain)) { DeleteMain(context); } _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain); } catch (Exception e) { LOG.Error(e, "Exception while executing Delete operation: {0}"); throw; } }
public void Create(CreateOpContext context) { ExchangeConnector exconn = (ExchangeConnector)context.Connector; Command cmdNew = ExchangeUtility.GetCommand( new PSExchangeConnector.CommandInfo(GetNewCommandName()), context.Attributes, exconn.Configuration); try { context.Uid = _helper.InvokePipelineAndGetGuid(exconn, cmdNew); } catch (ProxyAddressExistsException e) { // This is a tricky exception. Sometimes when creating an object that is already there (e.g. DistributionGroup), // PowerShell reports "ProxyAddressExists" instead of something like "ObjectExists" :( // So we have to distinguish these situations somehow... Name nameAttribute = ConnectorAttributeUtil.GetNameFromAttributes(context.Attributes); if (nameAttribute == null || nameAttribute.Value == null || nameAttribute.Value.Count() != 1) { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "ProxyAddressExistsException reported; but no single-valued NAME attribute present -- reporting as is"); throw new ConnectorException(e.Message, e); } String name = (String)nameAttribute.Value[0]; LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "ProxyAddressExistsException reported; trying to see if object named " + name + " exists"); Command cmdGet = ExchangeUtility.GetCommand( new PSExchangeConnector.CommandInfo(GetGetCommandName()), exconn.Configuration); cmdGet.Parameters.Add("Identity", name); ICollection <PSObject> objects; try { objects = _helper.InvokePipeline(exconn, cmdGet); } catch (ObjectNotFoundException e1) { objects = null; } if (objects == null || objects.Count == 0) { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "...it does not -- reporting as is"); throw new ConnectorException(e.Message, e); } else { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "...it exists -- reporting as AlreadyExistsException"); throw new AlreadyExistsException(e.Message, e); } } if (ExecuteSetAfterNew()) { Command cmdSet = ExchangeUtility.GetCommand( new PSExchangeConnector.CommandInfo(GetSetCommandName()), context.Attributes, context.Uid, exconn.Configuration); try { _helper.InvokePipeline(exconn, cmdSet); } catch { // TODO rollback // rethrow original exception throw; } } }
/// <summary> /// Inits the connector with configuration injected /// </summary> /// <param name="configuration">Initialized Exchange configuration</param> public override void Init(Configuration configuration) { base.Init(configuration); this.configuration = (ExchangeConfiguration)configuration; // create runspace instance, will be alive as long as the connector instance is alive this.runspace = new RunSpaceInstance(RunSpaceInstance.SnapIn.Exchange, configuration.ConnectorMessages); // read the object class info definitions this.mapOcInfo = ExchangeUtility.GetOCInfo(); }
/// <summary> /// Implementation of SearchOp.ExecuteQuery /// </summary> /// <param name="oclass">Object class</param> /// <param name="query">Query to execute</param> /// <param name="handler">Results handler</param> /// <param name="options">Operation options</param> public override void ExecuteQuery( ObjectClass oclass, string query, ResultsHandler handler, OperationOptions options) { ExchangeUtility.NullCheck(oclass, "oclass", this.configuration); // we handle accounts only if (!oclass.Is(ObjectClass.ACCOUNT_NAME)) { base.ExecuteQuery(oclass, query, handler, options); return; } ICollection <string> attsToGet = null; if (options != null && options.AttributesToGet != null) { attsToGet = CollectionUtil.NewList(options.AttributesToGet); } // delegate to get the exchange attributes if requested ResultsHandler filter = delegate(ConnectorObject cobject) { ConnectorObject filtered = ExchangeUtility.ReplaceAttributes( cobject, attsToGet, AttMapFromAD); filtered = this.AddExchangeAttributes(oclass, filtered, attsToGet); return(handler(filtered)); }; ResultsHandler handler2use = handler; OperationOptions options2use = options; if (options != null && options.AttributesToGet != null) { if (attsToGet.Contains(AttDatabase) || attsToGet.Contains(AttExternalMail) || attsToGet.Contains(AttRecipientType)) { // replace Exchange attributes with AD names var newAttsToGet = ExchangeUtility.FilterReplace(attsToGet, AttMap2AD); // we have to remove recipient type, as it is unknown to AD newAttsToGet.Remove(AttRecipientType); // build new op options var builder = new OperationOptionsBuilder(options); string[] attributesToGet = new string[newAttsToGet.Count]; newAttsToGet.CopyTo(attributesToGet, 0); builder.AttributesToGet = attributesToGet; options2use = builder.Build(); handler2use = filter; } } base.ExecuteQuery(oclass, query, handler2use, options2use); }
public Uid Update(UpdateType updateType, ObjectClass oclass, Uid uid, ICollection <ConnectorAttribute> attributes, OperationOptions options) { const string operation = "Update"; ExchangeUtility.NullCheck(updateType, "updateType", this._configuration); ExchangeUtility.NullCheck(oclass, "oclass", this._configuration); ExchangeUtility.NullCheck(uid, "uid", this._configuration); ExchangeUtility.NullCheck(attributes, "attributes", this._configuration); LOG.Info("Exchange.Update method; oclass = {0}, uid = {1}, type = {2}, attributes:\n{3}", oclass, uid, updateType, CommonUtils.DumpConnectorAttributes(attributes)); if (attributes == null || attributes.Count == 0) { LOG.Info("Returning immediately, as there are no attributes to modify."); return(uid); } String database = (String)ExchangeUtility.GetAttValue("Database", attributes); LOG.Info("Database attribute before plugins call: " + database); plugins.OnBeforeUpdate(oclass, uid, attributes, options, _configuration); database = (String)ExchangeUtility.GetAttValue("Database", attributes); LOG.Info("Database attribute after plugins call: " + database); UpdateOpContext context = new UpdateOpContext() { UpdateType = updateType, Attributes = attributes, Connector = this, ConnectorConfiguration = this._configuration, ObjectClass = oclass, OperationName = operation, Options = options, Uid = uid }; try { _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain); if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain)) { UpdateMain(context); } _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain); return(context.Uid); } catch (Exception e) { LOG.Error(e, "Exception while executing Update operation: {0}"); throw; } }
public void Delete(DeleteOpContext context) { ExchangeConnector exconn = (ExchangeConnector)context.Connector; Command cmdRemove = ExchangeUtility.GetCommand( new PSExchangeConnector.CommandInfo(GetRemoveCommandName()), context.Uid, exconn.Configuration); try { _helper.InvokePipeline(exconn, cmdRemove); } catch (ObjectNotFoundException e) { throw new UnknownUidException("Object with UID " + context.Uid.GetUidValue() + " couldn't be deleted", e); } }
/// <summary> /// Implementation of SynOp.Sync /// </summary> /// <param name="objClass">Object class</param> /// <param name="token">Sync token</param> /// <param name="handler">Sync results handler</param> /// <param name="options">Operation options</param> public override void Sync( ObjectClass objClass, SyncToken token, SyncResultsHandler handler, OperationOptions options) { ExchangeUtility.NullCheck(objClass, "oclass", this.configuration); // we handle accounts only if (!objClass.Is(ObjectClass.ACCOUNT_NAME)) { base.Sync(objClass, token, handler, options); return; } ICollection <string> attsToGet = null; if (options != null && options.AttributesToGet != null) { attsToGet = CollectionUtil.NewSet(options.AttributesToGet); } // delegate to get the exchange attributes if requested SyncResultsHandler xchangeHandler = delegate(SyncDelta delta) { if (delta.DeltaType == SyncDeltaType.DELETE) { return(handler(delta)); } // replace the ad attributes with exchange one and add recipient type ConnectorObject updated = ExchangeUtility.ReplaceAttributes(delta.Object, attsToGet, AttMapFromAD); updated = this.AddExchangeAttributes(objClass, updated, attsToGet); if (updated != delta.Object) { // build new sync delta, cause we changed the object SyncDeltaBuilder deltaBuilder = new SyncDeltaBuilder { DeltaType = delta.DeltaType, Token = delta.Token, Uid = delta.Uid, Object = updated }; delta = deltaBuilder.Build(); } return(handler(delta)); }; // call AD sync, use xchangeHandler base.Sync(objClass, token, xchangeHandler, options); }
public void Update(UpdateOpContext context) { ExchangeConnector exconn = (ExchangeConnector)context.Connector; ICollection <ConnectorAttribute> attributesForReplace = _helper.DetermineNewAttributeValues(context, context.Uid.GetUidValue()); // query string is the UID value! Command cmdSet = ExchangeUtility.GetCommand( new PSExchangeConnector.CommandInfo(GetSetCommandName()), attributesForReplace, context.Uid, exconn.Configuration); try { _helper.InvokePipeline(exconn, cmdSet); } catch (ObjectNotFoundException e) { throw new UnknownUidException("Object with UID " + context.Uid.GetUidValue() + " couldn't be modified", e); } }
public void Sync(SyncOpContext context) { ExchangeConnector exconn = (ExchangeConnector)context.Connector; ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector; ICollection <string> attsToGet = null; if (context.Options != null && context.Options.AttributesToGet != null) { attsToGet = CollectionUtil.NewSet(context.Options.AttributesToGet); } // delegate to get the exchange attributes if requested SyncResultsHandler xchangeHandler = new SyncResultsHandler() { Handle = delta => { if (delta.DeltaType == SyncDeltaType.DELETE) { return(context.SyncResultsHandler.Handle(delta)); } // replace the ad attributes with exchange ones and add recipient type and database (if requested) ConnectorObject updated = ExchangeUtility.ConvertAdAttributesToExchange(delta.Object); //updated = this.AddExchangeAttributes(exconn, context.ObjectClass, updated, attsToGet); if (updated != delta.Object) { // build new sync delta, cause we changed the object SyncDeltaBuilder deltaBuilder = new SyncDeltaBuilder { DeltaType = delta.DeltaType, Token = delta.Token, Uid = delta.Uid, Object = updated }; delta = deltaBuilder.Build(); } return(context.SyncResultsHandler.Handle(delta)); } }; // call AD sync, use xchangeHandler adconn.SyncInternal(context.ObjectClass, context.SyncToken, xchangeHandler, context.Options, GetAdAttributesToReturn(adconn, context.ObjectClass, context.Options)); }
public Uid Update(UpdateType updateType, ObjectClass oclass, Uid uid, ICollection <ConnectorAttribute> attributes, OperationOptions options) { const string operation = "Update"; ExchangeUtility.NullCheck(updateType, "updateType", this._configuration); ExchangeUtility.NullCheck(oclass, "oclass", this._configuration); ExchangeUtility.NullCheck(uid, "uid", this._configuration); ExchangeUtility.NullCheck(attributes, "attributes", this._configuration); LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Exchange.Update method; oclass = {0}, uid = {1}, type = {2}, attributes:\n{3}", oclass, uid, updateType, CommonUtils.DumpConnectorAttributes(attributes)); if (attributes == null || attributes.Count == 0) { LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Returning immediately, as there are no attributes to modify."); return(uid); } UpdateOpContext context = new UpdateOpContext() { UpdateType = updateType, Attributes = attributes, Connector = this, ConnectorConfiguration = this._configuration, ObjectClass = oclass, OperationName = operation, Options = options, Uid = uid }; try { _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain); if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain)) { UpdateMain(context); } _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain); return(context.Uid); } catch (Exception e) { LOGGER.TraceEvent(TraceEventType.Error, CAT_DEFAULT, "Exception while executing Update operation: {0}", e); throw; } }
/// <summary> /// helper method to filter out all attributes used in ExchangeConnector only /// </summary> /// <param name="attributes">Connector attributes</param> /// <param name="cmdInfos">CommandInfo whose parameters will be used and filtered out from attributes</param> /// <returns> /// Filtered connector attributes /// </returns> private static ICollection <ConnectorAttribute> FilterOut(ICollection <ConnectorAttribute> attributes, params PSExchangeConnector.CommandInfo[] cmdInfos) { IList <string> attsToRemove = new List <string> { AttRecipientType, AttDatabase, AttExternalMail }; if (cmdInfos != null) { foreach (PSExchangeConnector.CommandInfo cmdInfo in cmdInfos) { if (cmdInfo != null) { CollectionUtil.AddAll(attsToRemove, cmdInfo.Parameters); } } } return(ExchangeUtility.FilterOut(attributes, attsToRemove)); }
/// <summary> /// helper method to filter out all attributes used in ExchangeConnector only /// </summary> /// <param name="attributes">Connector attributes</param> /// <param name="cmdInfos">CommandInfo whose parameters will be used and filtered out from attributes</param> /// <returns> /// Filtered connector attributes /// </returns> internal static ICollection <ConnectorAttribute> FilterOut(ICollection <ConnectorAttribute> attributes, params PSExchangeConnector.CommandInfo[] cmdInfos) { IList <string> attsToRemove = new List <string> { ExchangeConnectorAttributes.AttRecipientType }; CollectionUtil.AddAll(attsToRemove, ExchangeConnectorAttributes.AttMap2AD.Keys); if (cmdInfos != null) { foreach (PSExchangeConnector.CommandInfo cmdInfo in cmdInfos) { if (cmdInfo != null) { CollectionUtil.AddAll(attsToRemove, cmdInfo.Parameters); } } } return(ExchangeUtility.FilterOut(attributes, attsToRemove)); }
/// <summary> /// Implementation of CreateOp.Create /// </summary> /// <param name="oclass">Object class</param> /// <param name="attributes">Object attributes</param> /// <param name="options">Operation options</param> /// <returns>Uid of the created object</returns> public Uid Create(ObjectClass oclass, ICollection <ConnectorAttribute> attributes, OperationOptions options) { const string operation = "Create"; ExchangeUtility.NullCheck(oclass, "oclass", this._configuration); ExchangeUtility.NullCheck(attributes, "attributes", this._configuration); LOG.Info("Exchange.Create method for {0}; attributes:\n{1}", oclass.GetObjectClassValue(), CommonUtils.DumpConnectorAttributes(attributes)); String database = (String)ExchangeUtility.GetAttValue("Database", attributes); LOG.Info("Database attribute before plugins call: " + database); plugins.OnBeforeCreate(oclass, attributes, options, _configuration); database = (String)ExchangeUtility.GetAttValue("Database", attributes); LOG.Info("Database attribute after plugins call: " + database); CreateOpContext context = new CreateOpContext() { Attributes = attributes, Connector = this, ConnectorConfiguration = this._configuration, ObjectClass = oclass, OperationName = operation, Options = options }; try { _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain); if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain)) { CreateMain(context); } _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain); return(context.Uid); } catch (Exception e) { LOG.Error(e, "Exception while executing Create operation: {0}"); throw; } }
public static string GetRecipientType(ConnectorObject cobject) { long?recipientTypeDetails = ExchangeUtility.GetAttValue(ExchangeConnectorAttributes.AttMsExchRecipientTypeDetailsADName, cobject.GetAttributes()) as long?; switch (recipientTypeDetails) // see http://blogs.technet.com/b/benw/archive/2007/04/05/exchange-2007-and-recipient-type-details.aspx { case 1: return(ExchangeConnectorAttributes.RcptTypeMailBox); case 128: return(ExchangeConnectorAttributes.RcptTypeMailUser); case null: // we are dealing with user accounts, so we can assume that an account without Exchange information is an ordinary User case 65536: return(ExchangeConnectorAttributes.RcptTypeUser); default: LOG.Warn("Unknown recipientTypeDetails: {0} ({1})", recipientTypeDetails, ExchangeUtility.GetAttValue(ExchangeConnectorAttributes.AttMsExchRecipientTypeDetailsADName, cobject.GetAttributes())); return(null); } }
/// <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><see cref="Uid"/> of the created object</returns> public override Uid Create( ObjectClass oclass, ICollection <ConnectorAttribute> attributes, OperationOptions options) { const string METHOD = "Create"; Debug.WriteLine(METHOD + ":entry", ClassName); // first create the object in AD Uid uid = base.Create(oclass, attributes, options); try { if (oclass.Is(MailboxName)) { // enable mailbox for person Command cmd = ExchangeUtility.GetCommand(CommandInfo.EnableMailbox, attributes, this.configuration); this.runspace.InvokePipeline(cmd); } else if (oclass.Is(MailUserName)) { // enable mailuser Command cmd = ExchangeUtility.GetCommand(CommandInfo.EnableMailUser, attributes, this.configuration); this.runspace.InvokePipeline(cmd); } Debug.WriteLine(METHOD + ":exit", ClassName); } catch { // do the rollback - delete the object by uid // no need to check the uid is null, ensured by the create contract this.Delete(oclass, uid, options); throw; } return(uid); }
/// <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> /// Implementation of SearchOp.ExecuteQuery /// </summary> /// <param name="oclass">Object class</param> /// <param name="query">Query to execute</param> /// <param name="handler">Results handler</param> /// <param name="options">Operation options</param> public void ExecuteQuery(ObjectClass oclass, string query, ResultsHandler handler, OperationOptions options) { const string operation = "ExecuteQuery"; ExchangeUtility.NullCheck(oclass, "oclass", this._configuration); if (options == null) { options = new OperationOptions(new Dictionary <string, object>()); } LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Exchange.ExecuteQuery method; oclass = {0}, query = {1}", oclass, query); ExecuteQueryContext context = new ExecuteQueryContext() { Connector = this, ConnectorConfiguration = _configuration, ObjectClass = oclass, OperationName = operation, Options = options, Query = query, ResultsHandler = handler }; try { _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain); if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain)) { ExecuteQueryMain(context); } _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain); } catch (Exception e) { LOGGER.TraceEvent(TraceEventType.Error, CAT_DEFAULT, "Exception while executing ExecuteQuery operation: {0}", e); throw; } // TODO what about executing a script on each returned item? }
/// <summary> /// Implementation of CreateOp.Create /// </summary> /// <param name="oclass">Object class</param> /// <param name="attributes">Object attributes</param> /// <param name="options">Operation options</param> /// <returns>Uid of the created object</returns> public Uid Create(ObjectClass oclass, ICollection <ConnectorAttribute> attributes, OperationOptions options) { const string operation = "Create"; ExchangeUtility.NullCheck(oclass, "oclass", this._configuration); ExchangeUtility.NullCheck(attributes, "attributes", this._configuration); LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Exchange.Create method for {0}; attributes:\n{1}", oclass.GetObjectClassValue(), CommonUtils.DumpConnectorAttributes(attributes)); CreateOpContext context = new CreateOpContext() { Attributes = attributes, Connector = this, ConnectorConfiguration = this._configuration, ObjectClass = oclass, OperationName = operation, Options = options }; try { _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain); if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain)) { CreateMain(context); } _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain); return(context.Uid); } catch (Exception e) { LOGGER.TraceEvent(TraceEventType.Error, CAT_DEFAULT, "Exception while executing Create operation: {0}", e); throw; } }
/// <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()); }
public void Update(UpdateOpContext context) { ExchangeConnector exconn = (ExchangeConnector)context.Connector; ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector; // update in AD first var filtered = ExchangeUtility.FilterOut( context.Attributes, PSExchangeConnector.CommandInfo.EnableMailbox, PSExchangeConnector.CommandInfo.EnableMailUser, PSExchangeConnector.CommandInfo.SetMailbox, PSExchangeConnector.CommandInfo.SetMailUser); adconn.Update(context.UpdateType, context.ObjectClass, context.Uid, filtered, context.Options); // retrieve Exchange-related information about the user string query = "(objectGUID=" + ActiveDirectoryUtils.ConvertUIDToSearchString(context.Uid) + ")"; ConnectorObject currentObject = _helper.GetCurrentObject(context, query); ICollection <ConnectorAttribute> attributesForReplace = _helper.DetermineNewAttributeValues(context, currentObject); attributesForReplace = DeduplicateEmailAddresses(context, attributesForReplace); string origRcptType; var newRcptType = _helper.DetermineOrigAndNewAttributeValue(context, currentObject, attributesForReplace, ExchangeConnectorAttributes.AttRecipientType, out origRcptType); if (newRcptType == null) { newRcptType = ExchangeConnectorAttributes.RcptTypeUser; } string origDatabase; var newDatabase = _helper.DetermineOrigAndNewAttributeValue(context, currentObject, attributesForReplace, ExchangeConnectorAttributes.AttDatabase, out origDatabase); // PART 1 - DEALING WITH MailUser CASE if (ExchangeConnectorAttributes.RcptTypeMailUser.Equals(newRcptType)) { // disabling Mailbox if needed if (ExchangeConnectorAttributes.RcptTypeMailBox.Equals(origRcptType)) { Command cmdDisable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.DisableMailbox, attributesForReplace, context.Uid, exconn.Configuration); cmdDisable.Parameters.Add("Confirm", false); _helper.InvokePipeline(exconn, cmdDisable); } // enabling MailUser if needed if (!ExchangeConnectorAttributes.RcptTypeMailUser.Equals(origRcptType)) { // Enable-MailUser needs the value of ExternalEmailAddress, so we have to get it string origExternalEmailAddress; var newExternalEmailAddress = _helper.DetermineOrigAndNewAttributeValue(context, currentObject, attributesForReplace, ExchangeConnectorAttributes.AttExternalEmailAddress, out origExternalEmailAddress); if (String.IsNullOrEmpty(newExternalEmailAddress)) { throw new InvalidOperationException("Missing ExternalEmailAddress value, which is required for a MailUser"); } ExchangeUtility.SetAttValue(ExchangeConnectorAttributes.AttExternalEmailAddress, newExternalEmailAddress, attributesForReplace); // now execute the Enable-MailUser command Command cmdEnable = ExchangeUtility.GetCommand( PSExchangeConnector.CommandInfo.EnableMailUser, attributesForReplace, context.Uid, exconn.Configuration); _helper.InvokePipeline(exconn, cmdEnable); } // setting MailUser attributes Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetMailUser, attributesForReplace, context.Uid, exconn.Configuration); _helper.InvokePipeline(exconn, cmdSet); } // PART 2 - DEALING WITH UserMailbox CASE else if (ExchangeConnectorAttributes.RcptTypeMailBox.Equals(newRcptType)) { // enable mailbox if necessary // 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 if (!ExchangeConnectorAttributes.RcptTypeMailBox.Equals(origRcptType)) { Command cmdEnable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.EnableMailbox, attributesForReplace, context.Uid, exconn.Configuration); _helper.InvokePipeline(exconn, cmdEnable); } else { // are we trying to update the database? if (newDatabase != null && origDatabase != null && !newDatabase.Equals(origDatabase)) { throw new ArgumentException( context.ConnectorConfiguration.ConnectorMessages.Format( "ex_not_updatable", "Update of [{0}] attribute is not supported", ExchangeConnectorAttributes.AttDatabase)); } } Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetMailbox, attributesForReplace, context.Uid, exconn.Configuration); _helper.InvokePipeline(exconn, cmdSet); } // PART 3 - DEALING WITH User CASE else if (ExchangeConnectorAttributes.RcptTypeUser.Equals(newRcptType)) { if (ExchangeConnectorAttributes.RcptTypeMailBox.Equals(origRcptType)) { Command cmdDisable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.DisableMailbox, attributesForReplace, context.Uid, exconn.Configuration); cmdDisable.Parameters.Add("Confirm", false); _helper.InvokePipeline(exconn, cmdDisable); } else if (ExchangeConnectorAttributes.RcptTypeMailUser.Equals(origRcptType)) { Command cmdDisable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.DisableMailUser, attributesForReplace, context.Uid, exconn.Configuration); cmdDisable.Parameters.Add("Confirm", false); _helper.InvokePipeline(exconn, cmdDisable); } else if (ExchangeConnectorAttributes.RcptTypeUser.Equals(origRcptType)) { // if orig is User, there is no need to disable anything } else { throw new InvalidOperationException("Invalid original recipient type: " + origRcptType); } Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetUser, attributesForReplace, context.Uid, exconn.Configuration); _helper.InvokePipeline(exconn, cmdSet); } else { // unsupported rcpt type throw new ArgumentException( context.ConnectorConfiguration.ConnectorMessages.Format( "ex_bad_rcpt", "Recipient type [{0}] is not supported", newRcptType)); } }
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; }
public void ExecuteQuery(ExecuteQueryContext context) { ExchangeConnector exconn = (ExchangeConnector)context.Connector; ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector; ICollection <string> attsToGet = null; if (context.Options != null && context.Options.AttributesToGet != null) { attsToGet = CollectionUtil.NewList(context.Options.AttributesToGet); } // delegate to get the exchange attributes if requested ResultsHandler filter = new SearchResultsHandler() { Handle = cobject => { LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Object returned from AD connector: {0}", CommonUtils.DumpConnectorAttributes(cobject.GetAttributes())); ConnectorObject filtered = ExchangeUtility.ConvertAdAttributesToExchange(cobject); //filtered = AddExchangeAttributes(exconn, context.ObjectClass, filtered, attsToGet); LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Object as passed from Exchange connector: {0}", CommonUtils.DumpConnectorAttributes(filtered.GetAttributes())); return(context.ResultsHandler.Handle(filtered)); }, HandleResult = result => { if (context.ResultsHandler is SearchResultsHandler) { ((SearchResultsHandler)context.ResultsHandler).HandleResult(result); } } }; ResultsHandler handler2use = filter; OperationOptions options2use = context.Options; // mapping AttributesToGet from Exchange to AD "language" // actually, we don't need this code any more, because there are no attribute that are not retrieved by default // Uncomment this code if necessary in the future. if (context.Options != null && context.Options.AttributesToGet != null) { /* * ISet<string> mappedExchangeAttributesToGet = new HashSet<string>(AttMap2AD.Keys); * mappedExchangeAttributesToGet.IntersectWith(options.AttributesToGet); * if (mappedExchangeAttributesToGet.Count > 0 || attsToGet.Contains(AttRecipientType)) * { * // replace Exchange attributes with AD names * var newAttsToGet = ExchangeUtility.FilterReplace(attsToGet, AttMap2AD); * * // we have to remove recipient type, as it is unknown to AD * newAttsToGet.Remove(AttRecipientType); * * // build new op options * var builder = new OperationOptionsBuilder(options); * string[] attributesToGet = new string[newAttsToGet.Count]; * newAttsToGet.CopyTo(attributesToGet, 0); * builder.AttributesToGet = attributesToGet; * options2use = builder.Build(); * } */ /* * if (attsToGet.Contains(ExchangeConnectorAttributes.AttDatabase)) * { * attsToGet.Remove(ExchangeConnectorAttributes.AttDatabase); * * // build new op options * var builder = new OperationOptionsBuilder(context.Options); * string[] attributesToGet = new string[attsToGet.Count]; * attsToGet.CopyTo(attributesToGet, 0); * builder.AttributesToGet = attributesToGet; * options2use = builder.Build(); * } */ } adconn.ExecuteQueryInternal(context.ObjectClass, context.Query, handler2use, options2use, GetAdAttributesToReturn(adconn, context.ObjectClass, context.Options)); }
/// <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); }