Umwandeln von Active Directory Datentypen in C#

Will man Information aus dem Active Directory in einer eigenen Applikation via System.DirectoryServices abfragen, so erfordert dies für manche Daten eine spezielle Umwandlung, um sie in C# weiter verarbeiten zu können.

Um dies zu erleichtern, folgt nun ein einfaches Beispiel für die Erweiterung von DirectoryEntry via Extension Methods.

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Principal;
using System.DirectoryServices;

namespace ExtensionDemo
{
    public static class DirectoryEntryExtensionMethods
    {
        public static string GetPropertyOfTypeString(this DirectoryEntry directoryEntry, string propertyName)
        {
            if (directoryEntry.Properties[propertyName].Value == null)
            {
                return null;
            }

            return directoryEntry.Properties[propertyName].Value.ToString();
        }

        public static DateTime? GetPropertyOfTypeDateTime(this DirectoryEntry directoryEntry, string propertyName)
        {
            if (directoryEntry.Properties[propertyName].Value == null)
            {
                return null;
            }

            return Convert.ToDateTime(directoryEntry.Properties[propertyName].Value);
        }

        public static long? GetPropertyOfTypeLong(this DirectoryEntry directoryEntry, string propertyName)
        {
            if (directoryEntry.Properties[propertyName].Value == null)
            {
                return null;
            }

            return ConvertActiveDirectoryLargeIntToLong(directoryEntry.Properties[propertyName].Value);
        }

        public static byte[] GetPropertyOfTypeByteArray(this DirectoryEntry directoryEntry, string propertyName)
        {
            if (directoryEntry.Properties[propertyName].Value == null)
            {
                return null;
            }

            return ConvertObjectToByteArray(directoryEntry.Properties[propertyName].Value);
        }

        public static Guid? GetPropertyOfTypeGuid(this DirectoryEntry directoryEntry, string propertyName)
        {
            if (directoryEntry.Properties[propertyName].Value == null)
            {
                return null;
            }

            return new Guid(directoryEntry.Properties[propertyName].Value as byte[]);
        }

        public static SecurityIdentifier GetPropertyOfTypeSecurityIdentifier(this DirectoryEntry directoryEntry, string propertyName)
        {
            if (directoryEntry.Properties[propertyName].Value == null)
            {
                return null;
            }

            byte[] byteSid = directoryEntry.Properties[propertyName].Value as byte[];
            return new SecurityIdentifier(byteSid, 0);
        }

        private static long ConvertActiveDirectoryLargeIntToLong(object activeDirectoryLargeInt)
        {
            int highPart = (int)activeDirectoryLargeInt.GetType().InvokeMember("HighPart", System.Reflection.BindingFlags.GetProperty, null, activeDirectoryLargeInt, null);
            int lowPart = (int)activeDirectoryLargeInt.GetType().InvokeMember("LowPart", System.Reflection.BindingFlags.GetProperty, null, activeDirectoryLargeInt, null);
            return (highPart * ((long)uint.MaxValue + 1)) + lowPart;
        }

        private static byte[] ConvertObjectToByteArray(Object objectToConvert)
        {
            if (objectToConvert == null) return null;
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            MemoryStream memoryStream;
            using (memoryStream = new MemoryStream())
            {
                binaryFormatter.Serialize(memoryStream, objectToConvert);
            }
            return memoryStream.ToArray();
        }
    }
}

Verwendet können die ExtensionMethods dann z.B. wie in folgendem Code-Ausschnitt gezeigt.

DirectorySearcher dirSearcher = new DirectorySearcher();
dirSearcher.SearchRoot = dirEntry;
dirSearcher.PageSize = 500;
dirSearcher.SearchScope = SearchScope.Subtree;
dirSearcher.Filter = searchFilter;
dirSearcher.PropertiesToLoad.Add("objectGUID");
dirSearcher.PropertiesToLoad.Add("objectSid");
dirSearcher.PropertiesToLoad.Add("dn");
dirSearcher.PropertiesToLoad.Add("cn");
dirSearcher.PropertiesToLoad.Add("displayName");
dirSearcher.PropertiesToLoad.Add("givenName");
dirSearcher.PropertiesToLoad.Add("uSNChanged");
dirSearcher.PropertiesToLoad.Add("whenChanged");
dirSearcher.PropertiesToLoad.Add("thumbnailPhoto");

SearchResultCollection resultCol = dirSearcher.FindAll();

foreach (SearchResult result in resultCol)
{
    ResultPropertyCollection propertiesCol = result.Properties;
    DirectoryEntry currentDirEntry = result.GetDirectoryEntry();

    Console.WriteLine($"cn: {currentDirEntry.GetPropertyOfTypeString("cn")}");
    Console.WriteLine($"displayname: {currentDirEntry.GetPropertyOfTypeString("displayname")}");
    Console.WriteLine($"distinguishedName: {currentDirEntry.GetPropertyOfTypeString("distinguishedName")}");
    Console.WriteLine($"givenname: {currentDirEntry.GetPropertyOfTypeString("givenname")}");
    Console.WriteLine($"objectGUID: {currentDirEntry.GetPropertyOfTypeGuid("objectGUID")}");
    Console.WriteLine($"objectSid: {currentDirEntry.GetPropertyOfTypeSecurityIdentifier("objectSid")}");
    Console.WriteLine($"uSNChanged: {currentDirEntry.GetPropertyOfTypeLong("uSNChanged")}");
    Console.WriteLine($"whenChanged: {currentDirEntry.GetPropertyOfTypeDateTime("whenChanged")}");
    Console.WriteLine($"whenCreated: {currentDirEntry.GetPropertyOfTypeDateTime("whenCreated")}");
    if(currentDirEntry.GetPropertyOfTypeByteArray("thumbnailPhoto") != null) { 
        Console.WriteLine($"thumbnailPhoto: {BitConverter.ToString(currentDirEntry.GetPropertyOfTypeByteArray("thumbnailPhoto"))}");
    }
}

Die Ausgabe für das Beispiel sieht dann so aus.

Scroll to top