7
\$\begingroup\$

This is a Windows Presentation Foundation application that queries active directory and can display lists of users, users by group, groups, and users by manager (direct reports). It operates on whatever active directory server the host computer belongs to, and dynamically builds a TreeView of all the Organizational Units in the active directory for the user to navigate through.

Once a user has selected an Organizational Unit, they can use one of the buttons to start a query. The results of the query are then displayed in a DataGrid.

Complete Process:

  1. Application Launch
    1. During the launch, the host AD server is contacted and a list of all OUs is retrieved.
    2. The OU list is parsed into a TreeView. Since the OUs are in the form of LDAP paths, this process involves:
      1. Storing the whole path as Path to be used later.
      2. Stripping the prefix, domain components, and OU individual prefixes, splitting into an array of individual OUs, and flipping the array (LDAP paths are "backwards").
      3. Creating an ActiveDirectoryScope for each individual OU, and assembling into a tree.
  2. Application Use
    1. User selects a scope from the TreeView.
    2. User selects a query.
      1. View notifies ViewModel that query has been requested.
      2. ViewModel retrieves current scope, and opens an ActiveDirectorySearcher on that scope.
      3. ViewModel retrieves the appropriate query from the searcher.
      4. ViewModel passes the query results into a DataPreparer with the appropriate attributes/fields to load.
      5. DataPreparer iterates through the query results and returns a list of dynamic objects with the appropriate attributes/fields.
      6. ViewModel transforms the list into a DataView and hands it to the View's DataGrid.

Notes:

  • For now, the attributes are specified in the form of readonly arrays. This will be changed later to user input.
  • The querying process will later be run in a background thread so that the UI doesn't freeze.
  • I know my implementation of MVVM is incorrect.
  • The get computers feature that appears in several different locations is currently not included, but will be later.
  • The blanket exception catch in the UsersGroups search is intentional and necessary to avoid an unknown error in a client's Active Directory.

ActiveDirectoryToolView.xaml

<Window x:Class="ActiveDirectoryToolWpf.ActiveDirectoryToolView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ActiveDirectoryToolWpf"
        mc:Ignorable="d"
        Title="ActiveDirectoryToolView" Height="576" Width="1024" MinHeight="576" MinWidth="1024">
    <Grid Margin="0,0,0,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="25*" />
            <ColumnDefinition Width="75*" />
        </Grid.ColumnDefinitions>
        <Grid Grid.Row="0">
            <Grid Grid.Column="0">
                <TreeView x:Name="TreeView"
                          ItemsSource="{Binding Path=Children}">
                    <TreeView.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
                            <TextBlock Text="{Binding}" />
                        </HierarchicalDataTemplate>
                    </TreeView.ItemTemplate>
                </TreeView>
            </Grid>
        </Grid>
        <Grid Grid.Column="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="42px" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                <Button x:Name="GetUsersButton" Content="Get Users" HorizontalAlignment="Left" Margin="10,10,0,0"
                        VerticalAlignment="Top" Width="75" Click="GetUsersButton_Click" />
                <Button x:Name="GetUsersGroupsButton" Content="Get Users' Groups" HorizontalAlignment="Left"
                        Margin="90,10,0,0" VerticalAlignment="Top" Width="103" Click="GetUsersGroupsButton_Click" />
                <Button x:Name="GetGroupsButton" Content="Get Groups" HorizontalAlignment="Left" Margin="198,10,0,0"
                        VerticalAlignment="Top" Width="75" Click="GetGroupsButton_Click" />
                <Button x:Name="GetDirectReports" Content="Get Direct Reports" HorizontalAlignment="Left"
                        Margin="278,10,0,0" VerticalAlignment="Top" Width="103" Click="GetDirectReports_Click" />
            </Grid>
            <Grid Grid.Row="1">
                <DataGrid x:Name="DataGrid"
                          AutoGenerateColumns="True"
                          HorizontalAlignment="Left"
                          Margin="10,10,0,0"
                          VerticalAlignment="Top"
                          RenderTransformOrigin="2.25,-3.615"
                          MaxHeight="9001" MaxWidth="90000000"
                          ItemsSource="{Binding IsAsync=True}" MinHeight="484" MinWidth="742" />
            </Grid>
        </Grid>
    </Grid>
</Window>

ActiveDirectoryToolView.cs

using System;
using System.Data;
using System.Windows;

namespace ActiveDirectoryToolWpf
{
    public partial class ActiveDirectoryToolView : IActiveDirectoryToolView
    {
        public ActiveDirectoryToolView()
        {
            ViewModel = new ActiveDirectoryToolViewModel(this);
            DataContext = new ActiveDirectoryScopeFetcher().Scope;
            InitializeComponent();
            DataGrid.EnableColumnVirtualization = true;
            DataGrid.EnableRowVirtualization = true;
        }

        public ActiveDirectoryToolViewModel ViewModel { get; }

        public event Action GetComputersClicked;

        public event Action GetDirectReportsClicked;

        public event Action GetGroupsClicked;

        public event Action GetUsersClicked;

        public event Action GetUsersGroupsClicked;

        public ActiveDirectoryScope Scope =>
            TreeView.SelectedItem as ActiveDirectoryScope;

        public void SetDataGridData(DataView dataView)
        {
            DataGrid.ItemsSource = dataView;
        }

        public void ShowMessage(string message)
        {
            MessageBox.Show(message);
        }

        public void ToggleEnabled()
        {
            IsEnabled = !IsEnabled;
        }

        private void GetDirectReports_Click(object sender, RoutedEventArgs e)
        {
            if (Scope != null)
                GetDirectReportsClicked?.Invoke();
        }

        private void GetGroupsButton_Click(object sender, RoutedEventArgs e)
        {
            if (Scope != null)
                GetGroupsClicked?.Invoke();
        }

        private void GetUsersButton_Click(object sender, RoutedEventArgs e)
        {
            if (Scope != null)
                GetUsersClicked?.Invoke();
        }

        private void GetUsersGroupsButton_Click(object sender, RoutedEventArgs e)
        {
            if (Scope != null)
                GetUsersGroupsClicked?.Invoke();
        }
    }
}

ActiveDirectoryToolViewModel.cs

using System.Data;
using System.Linq;

namespace ActiveDirectoryToolWpf
{
    public class ActiveDirectoryToolViewModel
    {
        private readonly ActiveDirectoryAttribute[]
            _defaultDirectReportsAttributes =
            {
                ActiveDirectoryAttribute.UserDisplayName,
                ActiveDirectoryAttribute.UserSamAccountName,
                ActiveDirectoryAttribute.DirectReportDisplayName,
                ActiveDirectoryAttribute.DirectReportSamAccountName
            };

        private readonly ActiveDirectoryAttribute[] _defaultGroupAttributes =
        {
            ActiveDirectoryAttribute.GroupSamAccountName,
            ActiveDirectoryAttribute.GroupManagedBy,
            ActiveDirectoryAttribute.GroupDescription,
            ActiveDirectoryAttribute.GroupDistinguishedName
        };

        private readonly ActiveDirectoryAttribute[] _defaultUserAttributes =
        {
            ActiveDirectoryAttribute.UserSurname,
            ActiveDirectoryAttribute.UserGivenName,
            ActiveDirectoryAttribute.UserDisplayName,
            ActiveDirectoryAttribute.UserSamAccountName,
            ActiveDirectoryAttribute.UserIsActive,
            ActiveDirectoryAttribute.UserIsAccountLockedOut,
            ActiveDirectoryAttribute.UserDescription,
            ActiveDirectoryAttribute.UserTitle,
            ActiveDirectoryAttribute.UserCompany,
            ActiveDirectoryAttribute.UserManager,
            ActiveDirectoryAttribute.UserHomeDrive,
            ActiveDirectoryAttribute.UserHomeDirectory,
            ActiveDirectoryAttribute.UserScriptPath,
            ActiveDirectoryAttribute.UserEmailAddress,
            ActiveDirectoryAttribute.UserStreetAddress,
            ActiveDirectoryAttribute.UserCity,
            ActiveDirectoryAttribute.UserState,
            ActiveDirectoryAttribute.UserVoiceTelephoneNumber,
            ActiveDirectoryAttribute.UserPager,
            ActiveDirectoryAttribute.UserMobile,
            ActiveDirectoryAttribute.UserFax,
            ActiveDirectoryAttribute.UserVoip,
            ActiveDirectoryAttribute.UserSip,
            ActiveDirectoryAttribute.UserUserPrincipalName,
            ActiveDirectoryAttribute.UserDistinguishedName
        };

        private readonly ActiveDirectoryAttribute[]
            _defaultUserGroupsAttributes =
            {
                ActiveDirectoryAttribute.UserSamAccountName,
                ActiveDirectoryAttribute.GroupSamAccountName,
                ActiveDirectoryAttribute.UserName,
                ActiveDirectoryAttribute.UserDistinguishedName
            };

        private readonly IActiveDirectoryToolView _view;
        private DataPreparer _dataPreparer;
        private ActiveDirectorySearcher _searcher;

        public ActiveDirectoryToolViewModel(IActiveDirectoryToolView view)
        {
            _view = view;
            _view.GetUsersClicked += OnGetUsers;
            _view.GetUsersGroupsClicked += OnGetUsersGroups;
            _view.GetDirectReportsClicked += OnGetDirectReports;
            _view.GetGroupsClicked += OnGetGroups;
        }

        private void OnGetDirectReports()
        {
            _searcher = new ActiveDirectorySearcher(_view.Scope);
            _dataPreparer = new DataPreparer
            {
                Data = _searcher.GetDirectReports(),
                Attributes = _defaultDirectReportsAttributes.ToList()
            };
            _view.SetDataGridData(
                _dataPreparer.GetResults().ToDataTable().AsDataView());
        }

        private void OnGetGroups()
        {
            _searcher = new ActiveDirectorySearcher(_view.Scope);
            _dataPreparer = new DataPreparer
            {
                Data = _searcher.GetGroups(),
                Attributes = _defaultGroupAttributes.ToList()
            };
            _view.SetDataGridData(
                _dataPreparer.GetResults().ToDataTable().AsDataView());
        }

        private void OnGetUsers()
        {
            _searcher = new ActiveDirectorySearcher(_view.Scope);
            _dataPreparer = new DataPreparer
            {
                Data = _searcher.GetUsers(),
                Attributes = _defaultUserAttributes.ToList()
            };
            _view.SetDataGridData(
                _dataPreparer.GetResults().ToDataTable().AsDataView());
        }

        private void OnGetUsersGroups()
        {
            _searcher = new ActiveDirectorySearcher(_view.Scope);
            _dataPreparer = new DataPreparer
            {
                Data = _searcher.GetUsersGroups(),
                Attributes = _defaultUserGroupsAttributes.ToList()
            };
            _view.SetDataGridData(
                _dataPreparer.GetResults().ToDataTable().AsDataView());
        }
    }
}

ActiveDirectoryScope.cs

using System;
using System.Collections.Generic;
using PrimitiveExtensions;

namespace ActiveDirectoryToolWpf
{
    public class ActiveDirectoryScope : IEquatable<ActiveDirectoryScope>
    {
        private const char Comma = ',';
        private const string DomainComponentPrefix = "DC=";
        private const string LdapProtocolPrefix = "LDAP://";
        private const char Period = '.';

        internal ActiveDirectoryScope()
        {
            Children = new List<ActiveDirectoryScope>();
        }

        public List<ActiveDirectoryScope> Children { get; set; }
        internal string Context => Path.Remove(LdapProtocolPrefix);

        internal string Domain
            => Path.SubstringAtIndexOfOrdinal(DomainComponentPrefix)
                .Remove(DomainComponentPrefix)
                .Replace(Comma, Period);

        internal string Name { get; set; }
        internal string Path { get; set; }

        public bool Equals(ActiveDirectoryScope other)
        {
            return Name == other.Name;
        }

        public override string ToString()
        {
            return Name;
        }

        internal void AddDirectoryScope(OrganizationalUnit organizationalUnit)
        {
            if (organizationalUnit.Split == null ||
                organizationalUnit.Split.Length < 1)
            {
                throw new ArgumentException(
                    "The organizational units array is null or empty!");
            }
            var parent = this;
            foreach (var level in organizationalUnit.Split)
            {
                var lastLevel = organizationalUnit.Split.Length - 1;
                if (parent.Children.Contains(new ActiveDirectoryScope
                {
                    Name = level
                }))
                {
                    parent = parent.Children.Find(
                        item => item.Name.Equals(level));
                }
                else if (level == organizationalUnit.Split[lastLevel])
                {
                    parent.Children.Add(new ActiveDirectoryScope
                    {
                        Name = level,
                        Path = organizationalUnit.Path
                    });
                }
            }
        }
    }
}

ActiveDirectoryScopeFetcher.cs

using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;

namespace ActiveDirectoryToolWpf
{
    public class ActiveDirectoryScopeFetcher
    {
        internal ActiveDirectoryScopeFetcher()
        {
            var rootPrincipalContext = new PrincipalContext(
                ContextType.Domain);
            var rootDirectoryEntry = new DirectoryEntry(
                rootPrincipalContext.ConnectedServer);
            Scope = new ActiveDirectoryScope
            {
                Name = rootDirectoryEntry.Path,
                Path = "LDAP://" + rootDirectoryEntry.Path
            };
            FetchScopeList();
        }

        public ActiveDirectoryScope Scope { get; set; }

        private void FetchScopeList()
        {
            using (var directorySearcher = new DirectorySearcher(Scope.Path))
            {
                directorySearcher.Filter =
                    "(objectCategory=organizationalUnit)";
                directorySearcher.PageSize = 1;
                foreach (SearchResult result in directorySearcher.FindAll())
                {
                    Scope.AddDirectoryScope(new OrganizationalUnit
                    {
                        Path = result.Path
                    });
                }
            }
            Scope.Children.Sort((a, b) => a.Name.CompareTo(b.Name));
        }
    }
}

ActiveDirectorySearcher.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.DirectoryServices.AccountManagement;
using System.Linq;

namespace ActiveDirectoryToolWpf
{
    public class ActiveDirectorySearcher
    {
        public ActiveDirectorySearcher(ActiveDirectoryScope scope)
        {
            Scope = scope;
        }

        private PrincipalContext PrincipalContext => new PrincipalContext(
            ContextType.Domain, Scope.Domain, Scope.Context);

        private ActiveDirectoryScope Scope { get; }

        public static IEnumerable<ComputerPrincipal> GetComputersFromContext(
            PrincipalContext context)
        {
            IEnumerable<ComputerPrincipal> computers;
            using (var searcher = new PrincipalSearcher(
                new ComputerPrincipal(context)))
            {
                computers =
                    searcher.FindAll().OfType<ComputerPrincipal>().ToList();
            }
            return computers;
        }

        public static IEnumerable<ComputerPrincipal> GetComputersFromGroup(
            GroupPrincipal group)
        {
            return group.GetMembers().OfType<ComputerPrincipal>();
        }

        public static IEnumerable<DirectReports> GetDirectReportsFromContext(
            PrincipalContext context)
        {
            return GetDirectReportsFromUsers(GetUsersFromContext(context));
        }

        public static IEnumerable<DirectReports> GetDirectReportsFromUsers(
            IEnumerable<UserPrincipal> users)
        {
            return users.Select(user => new DirectReports
            {
                User = user,
                Reports = user.GetDirectReports()
            }).ToList();
        }

        public static IEnumerable<GroupPrincipal> GetGroupsFromContext(
            PrincipalContext context)
        {
            return GetGroupsFromUsers(GetUsersFromContext(context));
        }

        public static IEnumerable<GroupPrincipal> GetGroupsFromUsers(
            IEnumerable<UserPrincipal> users)
        {
            var groups = new HashSet<GroupPrincipal>();
            foreach (var user in users)
            {
                groups.UnionWith(
                    user.GetGroups().OfType<GroupPrincipal>().ToList());
            }

            return groups;
        }

        public static IEnumerable<UserGroups> GetUserGroupsFromContext(
            PrincipalContext context)
        {
            return GetUserGroupsFromUsers(GetUsersFromContext(context));
        }

        public static IEnumerable<UserGroups> GetUserGroupsFromUsers(
            IEnumerable<UserPrincipal> users)
        {
            var userGroups = new List<UserGroups>();
            foreach (var user in users)
            {
                var groups = new List<GroupPrincipal>();
                try
                {
                    groups.AddRange(user.GetGroups().OfType<GroupPrincipal>());
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e.Message);
                }
                userGroups.Add(new UserGroups
                {
                    User = user,
                    Groups = groups
                });
            }
            return userGroups;
        }

        public static IEnumerable<UserPrincipal> GetUsersFromContext(
            PrincipalContext context)
        {
            IEnumerable<UserPrincipal> users;
            using (var searcher = new PrincipalSearcher(new UserPrincipal(
                context)))
            {
                users = searcher.FindAll().OfType<UserPrincipal>().ToList();
            }
            return users;
        }

        public static IEnumerable<UserPrincipal> GetUsersFromGroup(
            GroupPrincipal group)
        {
            return group.GetMembers().OfType<UserPrincipal>().ToList();
        }

        public IEnumerable<DirectReports> GetDirectReports()
        {
            return GetDirectReportsFromContext(PrincipalContext);
        }

        public IEnumerable<GroupPrincipal> GetGroups()
        {
            return GetGroupsFromContext(PrincipalContext);
        }

        public IEnumerable<UserPrincipal> GetUsers()
        {
            return GetUsersFromContext(PrincipalContext);
        }

        public IEnumerable<UserGroups> GetUsersGroups()
        {
            return GetUserGroupsFromContext(PrincipalContext);
        }
    }

    public class DirectReports : ExtendedPrincipalBase, IDisposable
    {
        public IEnumerable<UserPrincipal> Reports { get; set; }

        public void Dispose()
        {
            User?.Dispose();
            foreach (var report in Reports)
                report?.Dispose();
        }
    }

    public abstract class ExtendedPrincipalBase
    {
        public UserPrincipal User { get; set; }
    }

    public class UserGroups : ExtendedPrincipalBase, IDisposable
    {
        public IEnumerable<GroupPrincipal> Groups { get; set; }

        public void Dispose()
        {
            User?.Dispose();
            foreach (var group in Groups)
                group?.Dispose();
        }
    }
}

DataPreparer.cs

using System;
using System.Collections.Generic;
using System.Data;
using System.DirectoryServices.AccountManagement;
using System.Dynamic;
using System.Linq;
using static ActiveDirectoryToolWpf.ActiveDirectoryAttribute;

namespace ActiveDirectoryToolWpf
{
    public enum ActiveDirectoryAttribute
    {
        ComputerAccountExpirationDate,
        ComputerAccountLockoutTime,
        ComputerAllowReversiblePasswordEncryption,
        ComputerBadLogonCount,
        ComputerCertificates,
        ComputerContext,
        ComputerContextType,
        ComputerDelegationPermitted,
        ComputerDescription,
        ComputerDisplayName,
        ComputerDistinguishedName,
        ComputerEnabled,
        ComputerGuid,
        ComputerHomeDirectory,
        ComputerHomeDrive,
        ComputerLastBadPasswordAttempt,
        ComputerLastLogon,
        ComputerLastPasswordSet,
        ComputerName,
        ComputerPasswordNeverExpires,
        ComputerPasswordNotRequired,
        ComputerPermittedLogonTimes,
        ComputerPermittedWorkstations,
        ComputerSamAccountName,
        ComputerScriptPath,
        ComputerServicePrincipalNames,
        ComputerSid,
        ComputerSmartcardLogonRequired,
        ComputerStructuralObjectClass,
        ComputerUserCannotChangePassword,
        ComputerUserPrincipalName,
        DirectReportUserAccountControl,
        DirectReportAccountExpirationDate,
        DirectReportAccountLockoutTime,
        DirectReportAllowReversiblePasswordEncryption,
        DirectReportAssistant,
        DirectReportBadLogonCount,
        DirectReportCertificates,
        DirectReportCity,
        DirectReportComment,
        DirectReportCompany,
        DirectReportContext,
        DirectReportContextType,
        DirectReportCountry,
        DirectReportDelegationPermitted,
        DirectReportDepartment,
        DirectReportDescription,
        DirectReportDisplayName,
        DirectReportDistinguishedName,
        DirectReportDivision,
        DirectReportEmailAddress,
        DirectReportEmployeeId,
        DirectReportEnabled,
        DirectReportFax,
        DirectReportSuffix,
        DirectReportGivenName,
        DirectReportGuid,
        DirectReportHomeAddress,
        DirectReportHomeDirectory,
        DirectReportHomeDrive,
        DirectReportHomePhone,
        DirectReportInitials,
        DirectReportIsAccountLockedOut,
        DirectReportIsActive,
        DirectReportLastBadPasswordAttempt,
        DirectReportLastLogon,
        DirectReportLastPasswordSet,
        DirectReportManager,
        DirectReportMiddleName,
        DirectReportMobile,
        DirectReportName,
        DirectReportNotes,
        DirectReportPager,
        DirectReportPasswordNeverExpires,
        DirectReportPasswordNotRequired,
        DirectReportPermittedLogonTimes,
        DirectReportPermittedWorkstations,
        DirectReportSamAccountName,
        DirectReportScriptPath,
        DirectReportSid,
        DirectReportSip,
        DirectReportSmartcardLogonRequired,
        DirectReportState,
        DirectReportStreetAddress,
        DirectReportStructuralObjectClass,
        DirectReportSurname,
        DirectReportTitle,
        DirectReportUserCannotChangePassword,
        DirectReportUserPrincipalName,
        DirectReportVoiceTelephoneNumber,
        DirectReportVoip,
        GroupContext,
        GroupContextType,
        GroupDescription,
        GroupDisplayName,
        GroupDistinguishedName,
        GroupGuid,
        GroupIsSecurityGroup,
        GroupManagedBy,
        GroupMembers,
        GroupName,
        GroupSamAccountName,
        GroupScope,
        GroupSid,
        GroupStructuralObjectClass,
        GroupUserPrincipalName,
        UserUserAccountControl,
        UserAccountExpirationDate,
        UserAccountLockoutTime,
        UserAllowReversiblePasswordEncryption,
        UserAssistant,
        UserBadLogonCount,
        UserCertificates,
        UserCity,
        UserComment,
        UserCompany,
        UserContext,
        UserContextType,
        UserCountry,
        UserDelegationPermitted,
        UserDepartment,
        UserDescription,
        UserDisplayName,
        UserDistinguishedName,
        UserDivision,
        UserEmailAddress,
        UserEmployeeId,
        UserEnabled,
        UserFax,
        UserSuffix,
        UserGivenName,
        UserGuid,
        UserHomeAddress,
        UserHomeDirectory,
        UserHomeDrive,
        UserHomePhone,
        UserInitials,
        UserIsAccountLockedOut,
        UserIsActive,
        UserLastBadPasswordAttempt,
        UserLastLogon,
        UserLastPasswordSet,
        UserManager,
        UserMiddleName,
        UserMobile,
        UserName,
        UserNotes,
        UserPager,
        UserPasswordNeverExpires,
        UserPasswordNotRequired,
        UserPermittedLogonTimes,
        UserPermittedWorkstations,
        UserSamAccountName,
        UserScriptPath,
        UserSid,
        UserSip,
        UserSmartcardLogonRequired,
        UserState,
        UserStreetAddress,
        UserStructuralObjectClass,
        UserSurname,
        UserTitle,
        UserUserCannotChangePassword,
        UserUserPrincipalName,
        UserVoiceTelephoneNumber,
        UserVoip
    }

    internal static class Extensions
    {
        public static DataTable ToDataTable(this IEnumerable<dynamic> items)
        {
            var data = items.ToArray();
            if (!data.Any())
            {
                return null;
            }

            var dataTable = new DataTable();
            foreach (var key in ((IDictionary<string, object>) data[0]).Keys)
            {
                dataTable.Columns.Add(key);
            }
            foreach (var d in data)
            {
                dataTable.Rows.Add(
                    ((IDictionary<string, object>) d).Values.ToArray());
            }
            return dataTable;
        }
    }

    internal class DataPreparer
    {
        internal List<ActiveDirectoryAttribute> Attributes { get; set; }
        internal IEnumerable<object> Data { get; set; }

        internal List<ExpandoObject> GetResults()
        {
            var results = new List<ExpandoObject>();

            foreach (var data in Data)
            {
                GroupPrincipal groupPrincipal;
                UserPrincipal userPrincipal;
                if (data is UserGroups)
                {
                    var userGroups = data as UserGroups;
                    userPrincipal = userGroups.User;
                    foreach (var group in userGroups.Groups)
                    {
                        groupPrincipal = group;
                        dynamic result = new ExpandoObject();
                        AddAttributesToResult(
                            null, groupPrincipal, null, userPrincipal, result);
                        results.Add(result);
                    }
                    userGroups.Dispose();
                }
                else if (data is DirectReports)
                {
                    var directReports = data as DirectReports;
                    if (directReports.Reports == null) continue;
                    userPrincipal = directReports.User;
                    foreach (var directReport in directReports.Reports)
                    {
                        dynamic result = new ExpandoObject();
                        AddAttributesToResult(
                            null, null, directReport, userPrincipal, result);
                        results.Add(result);
                    }
                    directReports.Dispose();
                }
                else
                {
                    var computerPrincipal = data as ComputerPrincipal;
                    groupPrincipal = data as GroupPrincipal;
                    userPrincipal = data as UserPrincipal;
                    dynamic result = new ExpandoObject();
                    AddAttributesToResult(
                        computerPrincipal,
                        groupPrincipal,
                        null,
                        userPrincipal,
                        result);
                    results.Add(result);
                    var principal = data as Principal;
                    principal?.Dispose();
                }
            }
            return results;
        }

        private static bool AddComputerAttributeToResult(
            ComputerPrincipal principal,
            ActiveDirectoryAttribute attribute,
            dynamic result)
        {
            var attributeMapping =
                new Dictionary<ActiveDirectoryAttribute, Action>
                {
                    [ComputerAccountExpirationDate] = () =>
                        result.ComputerAccountExpirationDate =
                            principal.AccountExpirationDate,
                    [ComputerAccountLockoutTime] = () =>
                        result.ComputerAccountLockoutTime =
                            principal.AccountLockoutTime,
                    [ComputerAllowReversiblePasswordEncryption] = () =>
                        result.ComputerAllowReversiblePasswordEncryption =
                            principal.AllowReversiblePasswordEncryption,
                    [ComputerBadLogonCount] = () =>
                        result.ComputerBadLogonCount = principal.BadLogonCount,
                    [ComputerCertificates] = () =>
                        result.ComputerCertificates = principal.Certificates,
                    [ComputerContext] = () =>
                        result.ComputerContext = principal.Context,
                    [ComputerContextType] = () =>
                        result.ComputerContextType = principal.ContextType,
                    [ComputerDelegationPermitted] = () =>
                        result.ComputerDelegationPermitted =
                            principal.DelegationPermitted,
                    [ComputerDescription] = () =>
                        result.ComputerDescription = principal.Description,
                    [ComputerDisplayName] = () =>
                        result.ComputerDisplayName = principal.DisplayName,
                    [ComputerDistinguishedName] = () =>
                        result.ComputerDistinguishedName =
                            principal.DistinguishedName,
                    [ComputerEnabled] = () =>
                        result.ComputerEnabled = principal.Enabled,
                    [ComputerGuid] = () => result.ComputerGuid =
                        principal.Guid,
                    [ComputerHomeDirectory] = () =>
                        result.ComputerHomeDirectory = principal.HomeDirectory,
                    [ComputerHomeDrive] = () =>
                        result.ComputerHomeDrive = principal.HomeDrive,
                    [ComputerLastBadPasswordAttempt] = () =>
                        result.ComputerLastBadPasswordAttempt =
                            principal.LastBadPasswordAttempt,
                    [ComputerLastLogon] = () =>
                        result.ComputerLastLogon = principal.LastLogon,
                    [ComputerLastPasswordSet] = () =>
                        result.LastPasswordSet = principal.LastPasswordSet,
                    [ComputerName] = () => result.ComputerName =
                        principal.Name,
                    [ComputerPasswordNeverExpires] = () =>
                        result.ComputerPasswordNeverExpires =
                            principal.PasswordNeverExpires,
                    [ComputerPasswordNotRequired] = () =>
                        result.ComputerPasswordNotRequired =
                            principal.PasswordNotRequired,
                    [ComputerPermittedLogonTimes] = () =>
                        result.ComputerPermittedLogonTimes =
                            principal.PermittedLogonTimes,
                    [ComputerPermittedWorkstations] = () =>
                        result.ComputerPermittedWorkstations =
                            principal.PermittedWorkstations,
                    [ComputerSamAccountName] = () =>
                        result.ComputerSamAccountName =
                            principal.SamAccountName,
                    [ComputerScriptPath] = () =>
                        result.ComputerScriptPath = principal.ScriptPath,
                    [ComputerServicePrincipalNames] = () =>
                        result.ComputerServicePrincipalNames =
                            principal.ServicePrincipalNames,
                    [ComputerSid] = () => result.ComputerSid = principal.Sid,
                    [ComputerSmartcardLogonRequired] = () =>
                        result.ComputerSmartcardLogonRequired =
                            principal.SmartcardLogonRequired,
                    [ComputerStructuralObjectClass] = () =>
                        result.ComputerStructuralObjectClass =
                            principal.StructuralObjectClass,
                    [ComputerUserCannotChangePassword] = () =>
                        result.ComputerUserCannotChangePassword =
                            principal.UserCannotChangePassword,
                    [ComputerUserPrincipalName] = () =>
                        result.ComputerUserPrincipalName =
                            principal.UserPrincipalName
                };

            if (!attributeMapping.ContainsKey(attribute)) return false;
            attributeMapping[attribute]();
            return true;
        }

        private static bool AddDirectReportAttributeToResult(
            UserPrincipal principal,
            ActiveDirectoryAttribute attribute,
            dynamic result)
        {
            var attributeMapping =
                new Dictionary<ActiveDirectoryAttribute, Action>
                {
                    [DirectReportUserAccountControl] = () =>
                        result.DirectReportAccountControl =
                            principal.GetUserAccountControl(),
                    [DirectReportAccountExpirationDate] = () =>
                        result.DirectReportAccountExpirationDate =
                            principal.AccountExpirationDate,
                    [DirectReportAccountLockoutTime] = () =>
                        result.DirectReportAccountLockoutTime =
                            principal.AccountLockoutTime,
                    [DirectReportAllowReversiblePasswordEncryption] = () =>
                        result.DirectReportAllowReversiblePasswordEncryption =
                            principal.AllowReversiblePasswordEncryption,
                    [DirectReportAssistant] = () =>
                        result.DirectReportAssistant =
                            principal.GetAssistant(),
                    [DirectReportBadLogonCount] = () =>
                        result.DirectReportBadLogonCount =
                            principal.BadLogonCount,
                    [DirectReportCertificates] = () =>
                        result.DirectReportCertificates =
                            principal.Certificates,
                    [DirectReportCity] = () =>
                        result.DirectReportCity = principal.GetCity(),
                    [DirectReportComment] = () =>
                        result.DirectReportComment = principal.GetComment(),
                    [DirectReportCompany] = () =>
                        result.DirectReportCompany = principal.GetCompany(),
                    [DirectReportContext] = () =>
                        result.DirectReportContext = principal.Context,
                    [DirectReportContextType] = () =>
                        result.DirectReportContextType = principal.ContextType,
                    [DirectReportCountry] = () =>
                        result.DirectReportCountry = principal.GetCountry(),
                    [DirectReportDelegationPermitted] = () =>
                        result.DirectReportDelegationPermitted =
                            principal.DelegationPermitted,
                    [DirectReportDepartment] = () =>
                        result.DirectReportDepartment =
                            principal.GetDepartment(),
                    [DirectReportDescription] = () =>
                        result.DirectReportDescription = principal.Description,
                    [DirectReportDisplayName] = () =>
                        result.DirectReportDisplayName = principal.DisplayName,
                    [DirectReportDistinguishedName] = () =>
                        result.DirectReportDistinguishedName =
                            principal.DistinguishedName,
                    [DirectReportDivision] = () =>
                        result.DirectReportDivision = principal.GetDivision(),
                    [DirectReportEmailAddress] = () =>
                        result.DirectReportEmailAddress =
                            principal.EmailAddress,
                    [DirectReportEmployeeId] = () =>
                        result.DirectReportEmployeeId = principal.EmployeeId,
                    [DirectReportEnabled] = () =>
                        result.DirectReportEnabled = principal.Enabled,
                    [DirectReportFax] = () =>
                        result.DirectReportFax = principal.GetFax(),
                    [DirectReportSuffix] = () =>
                        result.DirectReportSuffix = principal.GetSuffix(),
                    [DirectReportGivenName] = () =>
                        result.DirectReportGivenName = principal.GivenName,
                    [DirectReportGuid] = () =>
                        result.DirectReportGuid = principal.Guid,
                    [DirectReportHomeAddress] = () =>
                        result.DirectReportHomeAddress =
                            principal.GetHomeAddress(),
                    [DirectReportHomeDirectory] = () =>
                        result.DirectReportHomeDirectory =
                            principal.HomeDirectory,
                    [DirectReportHomeDrive] = () =>
                        result.DirectReportHomeDrive = principal.HomeDrive,
                    [DirectReportHomePhone] = () =>
                        result.DirectReportHomePhone =
                            principal.GetHomePhone(),
                    [DirectReportInitials] = () =>
                        result.DirectReportInitials = principal.GetInitials(),
                    [DirectReportIsAccountLockedOut] = () =>
                        result.DirectReportIsAccountLockedOut =
                            principal.IsAccountLockedOut(),
                    [DirectReportIsActive] = () =>
                        result.DirectReportIsActive = principal.IsActive(),
                    [DirectReportLastBadPasswordAttempt] = () =>
                        result.DirectReportLastBadPasswordAttempt =
                            principal.LastBadPasswordAttempt,
                    [DirectReportLastLogon] = () =>
                        result.DirectReportLastLogon = principal.LastLogon,
                    [DirectReportLastPasswordSet] = () =>
                        result.DirectReportLastPasswordSet =
                            principal.LastPasswordSet,
                    [DirectReportManager] = () =>
                        result.DirectReportManager = principal.GetManager(),
                    [DirectReportMiddleName] = () =>
                        result.DirectReportMiddleName = principal.MiddleName,
                    [DirectReportMobile] = () =>
                        result.DirectReportMobile = principal.GetMobile(),
                    [DirectReportName] = () =>
                        result.DirectReportName = principal.Name,
                    [DirectReportNotes] = () =>
                        result.DirectReportNotes = principal.GetNotes(),
                    [DirectReportPager] = () =>
                        result.DirectReportPager = principal.GetPager(),
                    [DirectReportPasswordNeverExpires] = () =>
                        result.DirectReportPasswordNeverExpires =
                            principal.PasswordNeverExpires,
                    [DirectReportPasswordNotRequired] = () =>
                        result.DirectReportPasswordNotRequired =
                            principal.PasswordNotRequired,
                    [DirectReportPermittedLogonTimes] = () =>
                        result.DirectReportPermittedLogonTimes =
                            principal.PermittedLogonTimes,
                    [DirectReportPermittedWorkstations] = () =>
                        result.DirectReportPermittedWorkstations =
                            principal.PermittedWorkstations,
                    [DirectReportSamAccountName] = () =>
                        result.DirectReportSamAccountName =
                            principal.SamAccountName,
                    [DirectReportScriptPath] = () =>
                        result.DirectReportScriptPath = principal.ScriptPath,
                    [DirectReportSid] = () =>
                        result.DirectReportSid = principal.Sid,
                    [DirectReportSip] = () =>
                        result.DirectReportSip = principal.GetSip(),
                    [DirectReportSmartcardLogonRequired] = () =>
                        result.DirectReportSmartcardLogonRequired =
                            principal.SmartcardLogonRequired,
                    [DirectReportState] = () =>
                        result.DirectReportState = principal.GetState(),
                    [DirectReportStreetAddress] = () =>
                        result.DirectReportStreetAddress =
                            principal.GetStreetAddress(),
                    [DirectReportStructuralObjectClass] = () =>
                        result.DirectReportStructuralObjectClass =
                            principal.StructuralObjectClass,
                    [DirectReportSurname] = () =>
                        result.DirectReportSurname = principal.Surname,
                    [DirectReportTitle] = () =>
                        result.DirectReportTitle = principal.GetTitle(),
                    [DirectReportUserCannotChangePassword] = () =>
                        result.DirectReportUserCannotChangePassword =
                            principal.UserCannotChangePassword,
                    [DirectReportUserPrincipalName] = () =>
                        result.DirectReportUserPrincipalName =
                            principal.UserPrincipalName,
                    [DirectReportVoiceTelephoneNumber] = () =>
                        result.DirectReportVoiceTelephoneNumber =
                            principal.VoiceTelephoneNumber,
                    [DirectReportVoip] = () =>
                        result.DirectReportVoip = principal.GetVoip()
                };

            if (!attributeMapping.ContainsKey(attribute)) return false;
            attributeMapping[attribute]();
            return true;
        }

        private static bool AddGroupAttributeToResult(
            GroupPrincipal principal,
            ActiveDirectoryAttribute attribute,
            dynamic result)
        {
            var attributeMapping =
                new Dictionary<ActiveDirectoryAttribute, Action>
                {
                    [GroupContext] =
                        () => result.GroupContext = principal.Context,
                    [GroupContextType] = () =>
                        result.GroupContextType = principal.ContextType,
                    [GroupDescription] = () =>
                        result.GroupDescription = principal.Description,
                    [GroupDisplayName] = () =>
                        result.GroupDisplayName = principal.DisplayName,
                    [GroupDistinguishedName] = () =>
                        result.GroupDistinguishedName =
                            principal.DistinguishedName,
                    [GroupGuid] = () => result.GroupGuid = principal.Guid,
                    [GroupIsSecurityGroup] = () =>
                        result.GroupIsSecurityGroup =
                            principal.IsSecurityGroup,
                    [GroupManagedBy] = () =>
                        result.GroupManagedBy = principal.GetManagedBy(),
                    [GroupName] = () => result.GroupName = principal.Name,
                    [GroupSamAccountName] = () =>
                        result.GroupSamAccountName = principal.SamAccountName,
                    [ActiveDirectoryAttribute.GroupScope] = () =>
                        result.GroupScope = principal.GroupScope,
                    [GroupSid] = () => result.GroupSid = principal.Sid,
                    [GroupStructuralObjectClass] = () =>
                        result.GroupStructuralObjectClass =
                            principal.StructuralObjectClass,
                    [GroupUserPrincipalName] = () =>
                        result.GroupUserPrincipalName =
                            principal.UserPrincipalName,
                    [GroupMembers] =
                        () => result.GroupMembers = principal.Members
                };

            if (!attributeMapping.ContainsKey(attribute)) return false;
            attributeMapping[attribute]();
            return true;
        }

        private static void AddUserAttributeToResult(
            UserPrincipal principal,
            ActiveDirectoryAttribute attribute,
            dynamic result)
        {
            var attributeMapping =
                new Dictionary<ActiveDirectoryAttribute, Action>
                {
                    [UserUserAccountControl] = () =>
                        result.UserAccountControl =
                            principal.GetUserAccountControl(),
                    [UserAccountExpirationDate] = () =>
                        result.UserAccountExpirationDate =
                            principal.AccountExpirationDate,
                    [UserAccountLockoutTime] = () =>
                        result.UserAccountLockoutTime =
                            principal.AccountLockoutTime,
                    [UserAllowReversiblePasswordEncryption] = () =>
                        result.UserAllowReversiblePasswordEncryption =
                            principal.AllowReversiblePasswordEncryption,
                    [UserAssistant] = () =>
                        result.UserAssistant = principal.GetAssistant(),
                    [UserBadLogonCount] = () =>
                        result.UserBadLogonCount = principal.BadLogonCount,
                    [UserCertificates] = () =>
                        result.UserCertificates = principal.Certificates,
                    [UserCity] = () =>
                        result.UserCity = principal.GetCity(),
                    [UserComment] = () =>
                        result.UserComment = principal.GetComment(),
                    [UserCompany] = () =>
                        result.UserCompany = principal.GetCompany(),
                    [UserContext] = () =>
                        result.UserContext = principal.Context,
                    [UserContextType] = () =>
                        result.UserContextType = principal.ContextType,
                    [UserCountry] = () =>
                        result.UserCountry = principal.GetCountry(),
                    [UserDelegationPermitted] = () =>
                        result.UserDelegationPermitted =
                            principal.DelegationPermitted,
                    [UserDepartment] = () =>
                        result.UserDepartment = principal.GetDepartment(),
                    [UserDescription] = () =>
                        result.UserDescription = principal.Description,
                    [UserDisplayName] = () =>
                        result.UserDisplayName = principal.DisplayName,
                    [UserDistinguishedName] = () =>
                        result.UserDistinguishedName =
                            principal.DistinguishedName,
                    [UserDivision] = () =>
                        result.UserDivision = principal.GetDivision(),
                    [UserEmailAddress] = () =>
                        result.UserEmailAddress = principal.EmailAddress,
                    [UserEmployeeId] = () =>
                        result.UserEmployeeId = principal.EmployeeId,
                    [UserEnabled] = () =>
                        result.UserEnabled = principal.Enabled,
                    [UserFax] = () =>
                        result.UserFax = principal.GetFax(),
                    [UserSuffix] = () =>
                        result.UserSuffix = principal.GetSuffix(),
                    [UserGivenName] = () =>
                        result.UserGivenName = principal.GivenName,
                    [UserGuid] = () =>
                        result.UserGuid = principal.Guid,
                    [UserHomeAddress] = () =>
                        result.UserHomeAddress = principal.GetHomeAddress(),
                    [UserHomeDirectory] = () =>
                        result.UserHomeDirectory = principal.HomeDirectory,
                    [UserHomeDrive] = () =>
                        result.UserHomeDrive = principal.HomeDrive,
                    [UserHomePhone] = () =>
                        result.UserHomePhone = principal.GetHomePhone(),
                    [UserInitials] = () =>
                        result.UserInitials = principal.GetInitials(),
                    [UserIsAccountLockedOut] = () =>
                        result.UserIsAccountLockedOut =
                            principal.IsAccountLockedOut(),
                    [UserIsActive] = () =>
                        result.UserIsActive = principal.IsActive(),
                    [UserLastBadPasswordAttempt] = () =>
                        result.UserLastBadPasswordAttempt =
                            principal.LastBadPasswordAttempt,
                    [UserLastLogon] = () =>
                        result.UserLastLogon = principal.LastLogon,
                    [UserLastPasswordSet] = () =>
                        result.UserLastPasswordSet = principal.LastPasswordSet,
                    [UserManager] = () =>
                        result.UserManager = principal.GetManager(),
                    [UserMiddleName] = () =>
                        result.UserMiddleName = principal.MiddleName,
                    [UserMobile] = () =>
                        result.UserMobile = principal.GetMobile(),
                    [UserName] = () =>
                        result.UserName = principal.Name,
                    [UserNotes] = () =>
                        result.UserNotes = principal.GetNotes(),
                    [UserPager] = () =>
                        result.UserPager = principal.GetPager(),
                    [UserPasswordNeverExpires] = () =>
                        result.UserPasswordNeverExpires =
                            principal.PasswordNeverExpires,
                    [UserPasswordNotRequired] = () =>
                        result.UserPasswordNotRequired =
                            principal.PasswordNotRequired,
                    [UserPermittedLogonTimes] = () =>
                        result.UserPermittedLogonTimes =
                            principal.PermittedLogonTimes,
                    [UserPermittedWorkstations] = () =>
                        result.UserPermittedWorkstations =
                            principal.PermittedWorkstations,
                    [UserSamAccountName] = () =>
                        result.UserSamAccountName = principal.SamAccountName,
                    [UserScriptPath] = () =>
                        result.UserScriptPath = principal.ScriptPath,
                    [UserSid] = () =>
                        result.UserSid = principal.Sid,
                    [UserSip] = () =>
                        result.UserSip = principal.GetSip(),
                    [UserSmartcardLogonRequired] = () =>
                        result.UserSmartcardLogonRequired =
                            principal.SmartcardLogonRequired,
                    [UserState] = () =>
                        result.UserState = principal.GetState(),
                    [UserStreetAddress] = () =>
                        result.UserStreetAddress =
                            principal.GetStreetAddress(),
                    [UserStructuralObjectClass] = () =>
                        result.UserStructuralObjectClass =
                            principal.StructuralObjectClass,
                    [UserSurname] = () =>
                        result.UserSurname = principal.Surname,
                    [UserTitle] = () =>
                        result.UserTitle = principal.GetTitle(),
                    [UserUserCannotChangePassword] = () =>
                        result.UserUserCannotChangePassword =
                            principal.UserCannotChangePassword,
                    [UserUserPrincipalName] = () =>
                        result.UserUserPrincipalName =
                            principal.UserPrincipalName,
                    [UserVoiceTelephoneNumber] = () =>
                        result.UserVoiceTelephoneNumber =
                            principal.VoiceTelephoneNumber,
                    [UserVoip] = () =>
                        result.UserVoip = principal.GetVoip()
                };

            if (!attributeMapping.ContainsKey(attribute)) return;
            attributeMapping[attribute]();
        }

        private void AddAttributesToResult(
            ComputerPrincipal computerPrincipal,
            GroupPrincipal groupPrincipal,
            UserPrincipal directReportUserPrincipal,
            UserPrincipal userPrincipal,
            dynamic result)
        {
            foreach (var attribute in Attributes)
            {
                if (computerPrincipal != null)
                {
                    if (AddComputerAttributeToResult(
                        computerPrincipal, attribute, result))
                    {
                        continue;
                    }
                }
                if (directReportUserPrincipal != null)
                {
                    if (AddDirectReportAttributeToResult(
                        directReportUserPrincipal, attribute, result))
                    {
                        continue;
                    }
                }
                if (groupPrincipal != null)
                {
                    if (AddGroupAttributeToResult(
                        groupPrincipal, attribute, result))
                    {
                        continue;
                    }
                }
                if (userPrincipal != null)
                {
                    AddUserAttributeToResult(userPrincipal, attribute, result);
                }
            }
        }
    }
}

OrganizationalUnit.cs

using System;

namespace ActiveDirectoryToolWpf
{
    internal class OrganizationalUnit
    {
        private const char Comma = ',';
        private const string DomainComponentPrefix = ",DC=";
        private const string LdapProtocol = "LDAP://";
        private const string OrganizationalUnitPrefix = "OU=";
        private const int StringStartIndex = 0;

        internal string Path { get; set; }

        internal string[] Split
        {
            get
            {
                var namesOnly = Path.Replace(LdapProtocol, string.Empty)
                    .Replace(OrganizationalUnitPrefix, string.Empty);
                var firstDomainComponentIndex = namesOnly.IndexOf(
                    DomainComponentPrefix, StringComparison.Ordinal);
                namesOnly = namesOnly.Substring(
                    StringStartIndex, firstDomainComponentIndex);
                var split = namesOnly.Split(Comma);
                Array.Reverse(split);
                return split;
            }
        }
    }
}

I have omitted several classes that provide only extension methods, as I am out of room.

\$\endgroup\$
3
+50
\$\begingroup\$

Only scratching the surface...

ActiveDirectoryScope

The AddDirectoryScope() method can be improved by storing the value of the organizationalUnit.Split property (which by the way reads more like a method) into a variable.

Right now you are acessing that property at least four times and if an ActiveDirectoryScope with the level isn't contained in parent.Children it will be called one more time.

So changing to

    internal void AddDirectoryScope(OrganizationalUnit organizationalUnit)
    {
        string[] levels = organizationalUnit.Split;
        if (levels == null ||
            levels < 1)
        {
            throw new ArgumentException(
                "The organizational units array is null or empty!");
        }

        var parent = this;

        var lastLevel = levels.Length - 1;
        foreach (var level in levels)
        {
            if (parent.Children.Contains(new ActiveDirectoryScope
            {
                Name = level
            }))
            {
                parent = parent.Children.Find(
                    item => item.Name.Equals(level));
            }
            else if (level == levels[lastLevel])
            {
                parent.Children.Add(new ActiveDirectoryScope
                {
                    Name = level,
                    Path = organizationalUnit.Path
                });
            }
        }
    }  

will result in only one call to Split. I used the name levels but I am unsure if that will be good. I just went along with level.

But this can still be improved by extracting the creation of the ActiveDirectoryScope out of the if statement like so

    internal void AddDirectoryScope(OrganizationalUnit organizationalUnit)
    {
        string[] levels = organizationalUnit.Split;
        if (levels == null ||
            levels < 1)
        {
            throw new ArgumentException(
                "The organizational units array is null or empty!");
        }

        var parent = this;

        var lastLevel = levels.Length - 1;
        foreach (var level in levels)
        {
            var scope = new ActiveDirectoryScope
            {
                Name = level
            }

            if (parent.Children.Contains(scope)
            {
                parent = parent.Children.Find(
                    item => item.Name.Equals(level));
            }
            else if (level == levels[lastLevel])
            {
                scope.Path = organizationalUnit.Path;
                parent.Children.Add(scope);
            }
        }
    }

ActiveDirectorySearcher

The almost silently swallowing of the exception in GetUserGroupsFromUsers() isn't that good, in addition catching Exception only shouldn't be done either. You should always catch the most narrowed down exception.

As you have commented

The exception catching is because of some error in the client's active directory. It is an "Unknown Error" that only throws an Exception

I would like to suggest to add a comment to that catching of Exception so it is clear to any future reader of your code why you are doing it in the way it is.


internal static class Extensions

    var data = items.ToArray();
    if (!data.Any())
    {
        return null;
    }  

here you already have a dynamic[] so you should use data.Length == 0 which doesn't involve an enumerator like the Any() method.

\$\endgroup\$
  • \$\begingroup\$ The exception catching is because of some error in the client's active directory. It is an "Unknown Error" that only throws an Exception, nothing more specific than that. \$\endgroup\$ – Michael Brandon Morris Jun 20 '16 at 13:37
  • 1
    \$\begingroup\$ Didn't know that. Doing ActiveDirectory stuff not in a long run ( had been in my VB 6 days). Edited answer. \$\endgroup\$ – Heslacher Jun 20 '16 at 13:41
  • \$\begingroup\$ You couldn't have known, so I apologize. I was just trying to explain why it was there. I'll add it to the question. \$\endgroup\$ – Michael Brandon Morris Jun 20 '16 at 13:43
  • 1
    \$\begingroup\$ I re-read your comment and decided to let it in my answer, but changed it a little bit regarding your comment. \$\endgroup\$ – Heslacher Jun 20 '16 at 13:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.