using System.DirectoryServices; using System.Collections; using Microsoft.VisualBasic.CompilerServices; using System.Reflection; namespace DigitalData.Core.ConsoleApp { public class DirectoryService { public static T MapResultProperty(ResultPropertyCollection rpc) where T : new() { if (!OperatingSystem.IsWindows()) throw new PlatformNotSupportedException("The method is only supported on the Windows platform."); T resultObject = new(); foreach (string propertyName in rpc.PropertyNames ?? throw new ArgumentNullException("PropertyNames are null")) { var propertyValue = rpc[propertyName][0]; PropertyInfo? pi = typeof(T).GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); if (pi != null && propertyValue != null) { Type propertyType = pi.PropertyType; Type underlyingType = Nullable.GetUnderlyingType(propertyType) ?? propertyType; if (propertyType != underlyingType) { propertyValue = Convert.ChangeType(propertyValue, underlyingType); pi.SetValue(resultObject, propertyValue); } else if (typeof(IEnumerable).IsAssignableFrom(propertyType) && propertyType != typeof(string)) { var itemType = propertyType.GetGenericArguments()[0]; IList list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(itemType)); list.Add(Convert.ChangeType(propertyValue, itemType)); pi.SetValue(resultObject, list); } else if (propertyValue is byte[] && propertyType == typeof(string)) { pi.SetValue(resultObject, Convert.ToBase64String((byte[])propertyValue)); } else if (propertyValue is byte[] stBytes && propertyType == typeof(string)) { pi.SetValue(resultObject, BitConverter.ToString(stBytes).Replace("-", "")); } else if (propertyValue is byte[] guiBytes && propertyType == typeof(Guid)) { pi.SetValue(resultObject, new Guid(guiBytes)); } else { propertyValue = Convert.ChangeType(propertyValue, propertyType); pi.SetValue(resultObject, propertyValue); } } } return resultObject; } public static SearchResultCollection Search(string filter) { if (!OperatingSystem.IsWindows()) throw new PlatformNotSupportedException("The ListGroups method is only supported on the windows platform."); DirectorySearcher directorySearcher = new() { SearchScope = SearchScope.Subtree, SizeLimit = 50000, Filter = filter, }; return directorySearcher.FindAll(); } public static IEnumerable Search(string filter) where T: new() { List list = new(); foreach(SearchResult result in Search(filter)) { if (!OperatingSystem.IsWindows()) throw new PlatformNotSupportedException("The ListGroups method is only supported on the windows platform."); ResultPropertyCollection rpc = result.Properties; T obj = MapResultProperty(rpc); list.Add(obj); } return list; } public List ListGroups(string query) { if (OperatingSystem.IsWindows()) { DirectorySearcher directorySearcher = new() { SearchScope = SearchScope.Subtree, SizeLimit = 50000, Filter = query }; SearchResultCollection result = directorySearcher.FindAll(); return GroupResultsToList(result); } throw new PlatformNotSupportedException("The ListGroups method is only supported on the Windows platform."); } private List GroupResultsToList(SearchResultCollection results) { List list = new(); foreach(SearchResult result in results) { list.Add(new ADGroup { Name = TryGetProperty(result, "name"), SAMAccountName = TryGetProperty(result, "samaccountname"), CN = TryGetProperty(result, "cn"), Description = TryGetProperty(result, "description"), DistinguishedName = TryGetProperty(result, "distinguishedName"), ObjectCategory = TryGetProperty(result, "objectCategory"), //ObjectClass = TryGetProperty(result, "objectClass") }); } return list; } private string TryGetProperty(SearchResult Result, string PropertyName) { var messages = new List(); try { return Conversions.ToString(Result.Properties[PropertyName][0]); } catch (Exception ex) { Exception ex2 = ex; messages.Add(String.Format("Property {0} not found", PropertyName)); string empty = string.Empty; return empty; } } } }