FrameworkExtensions.DirectoryServices 1.0.0.43

dotnet add package FrameworkExtensions.DirectoryServices --version 1.0.0.43
                    
NuGet\Install-Package FrameworkExtensions.DirectoryServices -Version 1.0.0.43
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FrameworkExtensions.DirectoryServices" Version="1.0.0.43" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FrameworkExtensions.DirectoryServices" Version="1.0.0.43" />
                    
Directory.Packages.props
<PackageReference Include="FrameworkExtensions.DirectoryServices" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FrameworkExtensions.DirectoryServices --version 1.0.0.43
                    
#r "nuget: FrameworkExtensions.DirectoryServices, 1.0.0.43"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FrameworkExtensions.DirectoryServices@1.0.0.43
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FrameworkExtensions.DirectoryServices&version=1.0.0.43
                    
Install as a Cake Addin
#tool nuget:?package=FrameworkExtensions.DirectoryServices&version=1.0.0.43
                    
Install as a Cake Tool

Extensions to DirectoryServices

Build Tests

Last Commit NuGet Version License

Extension methods for Active Directory account management and Windows impersonation, part of Hawkynt's .NET Framework Extensions.

Property Value
Package ID FrameworkExtensions.DirectoryServices
Target Frameworks .NET Framework 3.5/4.0/4.5/4.8, .NET Standard 2.0, .NET Core 3.1, .NET 6.0
License LGPL-3.0-or-later

Overview

This library provides extension methods for GroupPrincipal, UserPrincipal, and Principal that simplify common Active Directory operations such as resolving group memberships (including nested groups), looking up users by various identity attributes, querying LDAP group properties, and performing Windows user impersonation. Results are cached using thread-safe concurrent dictionaries for high-performance repeated lookups. On .NET 5+ all AD-related classes are annotated with [SupportedOSPlatform("windows")].


API Reference

GroupPrincipal Extensions (System.DirectoryServices.AccountManagement.GroupPrincipal)

Static class: GroupPrincipalExtensions

Method Signature Description
GetAllMembers GetAllMembers(this GroupPrincipal, bool allowCached = false) -> IEnumerable<UserPrincipal> Recursively resolves all UserPrincipal members of a group, including nested group memberships. Uses a case-insensitive hash set of SAM account names to detect and avoid cycles. Results can be cached across calls when allowCached is true.
TryGetGroupFromSamAccountName TryGetGroupFromSamAccountName(string samAccountName, out GroupPrincipal group) -> bool (Static) Attempts to find a GroupPrincipal by SAM account name in the shared domain context. Returns true if a group was found; writes the result to group.

Principal Extensions (System.DirectoryServices.AccountManagement.Principal)

Static class: PrincipalExtensions

Method Signature Description
ResolveUsersForSamAccountName ResolveUsersForSamAccountName(string samAccountName, bool allowCached = false) -> IEnumerable<UserPrincipal> (Static) Resolves a SAM account name to one or more UserPrincipal instances. If the name identifies a group, returns all resolved group members. If it identifies a user, returns a singleton collection. Returns empty if no match is found.

UserPrincipal Extensions (System.DirectoryServices.AccountManagement.UserPrincipal)

Static class: UserPrincipalExtensions

User Name Methods
Method Signature Description
GetFullName GetFullName(this UserPrincipal, bool surnameFirst = false) -> string Constructs a full name string from GivenName, MiddleName, and Surname. When surnameFirst is true, formats as Surname, GivenName MiddleName. Falls back to SamAccountName if no name components are available.
GetEmailAddress GetEmailAddress(this UserPrincipal) -> MailAddress Creates a System.Net.Mail.MailAddress from the user's EmailAddress property and full name, UTF-8 encoded.
User Lookup Methods
Method Signature Description
FindDomainUserBySamAccountName FindDomainUserBySamAccountName(string samAccountName) -> UserPrincipal (Static) Finds a domain user by SAM account name. Always performs a fresh directory lookup. Returns null if not found.
FindDomainUserBySamAccountName FindDomainUserBySamAccountName(string samAccountName, bool allowCached) -> UserPrincipal (Static) Finds a domain user by SAM account name. When allowCached is true, uses a thread-safe ConcurrentDictionary cache to avoid repeated lookups.
FindFirstDomainUserByDisplayName FindFirstDomainUserByDisplayName(string fullName, bool allowCached = false) -> UserPrincipal (Static) Finds the first user whose display name matches the specified full name (comma-separated parts are joined with spaces). Returns null if not found.
FindFirstDomainUserByAnyName FindFirstDomainUserByAnyName(string name, bool allowCached = false) -> UserPrincipal (Static) Searches for a user by SAM account name first, then display name, then surname, returning the first match. Returns null if not found.
LDAP Group Methods
Method Signature Description
GetLDAPGroups GetLDAPGroups(this UserPrincipal) -> IEnumerable<ILDAPGroup> Returns the direct LDAP group memberships of the user as ILDAPGroup instances. Uses an internal LDAP cache keyed by distinguished name.
GetAllLDAPGroups GetAllLDAPGroups(this UserPrincipal) -> IEnumerable<ILDAPGroup> Recursively returns all LDAP group memberships (direct and transitive), performing depth-first traversal with cycle detection via a hash set of distinguished names.

ILDAPGroup (interface)

Namespace: System.DirectoryServices.AccountManagement

Represents the full set of LDAP group attributes as defined in Active Directory schema. For attribute descriptions see selfADSI: Group Attributes.

Category Properties
Identity CN, Name, DistinguishedName, SamAccountName, ObjectGUID, ObjectSid, ObjectCategory, ObjectClass
Display DisplayName, DisplayNamePrintable, AdminDisplayName, AdminDescription, Description
Exchange / Mail Mail, MailNickName, LegacyExchangeDN, MsExchExpansionServerName, MsExchHideFromAddressLists, MsExchHomeServerName, MsExchRequireAuthToSendTo, ProxyAddresses, TextEncodedORAddress
Group Membership Member, MemberOf (returns IEnumerable<ILDAPGroup>), GroupType, PrimaryGroupToken
Permissions AuthOrig, AuthOrigBL, DLMemRejectPerms, DLMemRejectPermsBL, DLMemSubmitPerms, DLMemSubmitPermsBL, UnauthOrig, UnauthOrigBL
Timestamps CreateTimeStamp, ModifyTimeStamp, WhenChanged, WhenCreated, USNChanged, USNCreated, IsDeleted
Directory ADsPath, CanonicalName, Class, Parent, HomeMTA, NTSecurityDescriptor
Management ManagedBy, Info, TelephoneNumber, DelivContLength
Unix/SFU MsSFU30GidNumber, MsSFU30Name, MsSFU30NisDomain, MsSFU30PosixMember
Delivery OOFReplyToOriginator, ReportToOriginator, ReportToOwner
Extension ExtensionAttribute

ILDAPCache (interface)

Namespace: System.DirectoryServices.AccountManagement

Controls the LDAP directory entry cache behavior.

Property Description
CacheEntryCount { get; set; } Gets or sets the maximum number of DirectoryEntry instances retained in the cache. Default: 512. Least-recently-used entries are evicted when the limit is exceeded.

Impersonation (class)

Namespace: System.Security

Availability: .NET Framework only (excluded from .NET Core, .NET 5+, and .NET Standard)

An IDisposable class that performs Windows user impersonation via the Win32 LogonUser API and WindowsIdentity.Impersonate. The impersonation context is automatically reverted when the object is disposed.

Enumerations
Enum Values Description
LogonType Interactive (2), Network (3), Batch (4), Service (5), Unlock (7), NetworkCleartext (8), NewCredentials (9) Specifies the type of logon operation to perform.
LogonProvider Default (0), WinNT35 (1), WinNT40_NTLM (2), WinNT50 (3) Specifies the logon provider to use for authentication.
Constructors
Constructor Description
Impersonation(string username, string password, LogonType type = Interactive, LogonProvider provider = Default) Impersonates the specified user in the current domain. Obtains the domain name automatically from Domain.GetCurrentDomain().
Impersonation(string domain, string username, string password, LogonType type = Interactive, LogonProvider provider = Default) Impersonates the specified user in the given domain. Throws InvalidCredentialException for unknown username or bad password (Win32 error 1326). Throws ApplicationException for other logon failures.
Methods
Method Description
Dispose() Reverts the impersonation context and releases the logon token handle. Safe to call multiple times.

Usage Examples

Resolving all members of a group (including nested)

using System.DirectoryServices.AccountManagement;

using var context = new PrincipalContext(ContextType.Domain);
var group = GroupPrincipal.FindByIdentity(context, "Developers");
foreach (var member in group.GetAllMembers(allowCached: true))
  Console.WriteLine(member.SamAccountName);

Resolving users from a SAM account name (user or group)

using System.DirectoryServices.AccountManagement;

// Works for both users and groups
foreach (var user in PrincipalExtensions.ResolveUsersForSamAccountName("dev-team"))
  Console.WriteLine(user.EmailAddress);

Looking up a user by any name

using System.DirectoryServices.AccountManagement;

var user = UserPrincipalExtensions.FindFirstDomainUserByAnyName("John Smith");
if (user != null) {
  Console.WriteLine(user.GetFullName(surnameFirst: true)); // "Smith, John"
  Console.WriteLine(user.GetEmailAddress());               // "John Smith" <jsmith@example.com>
}

Querying LDAP groups

using System.DirectoryServices.AccountManagement;

using var context = new PrincipalContext(ContextType.Domain);
var user = UserPrincipal.FindByIdentity(context, "jdoe");

// Direct groups only
foreach (var group in user.GetLDAPGroups())
  Console.WriteLine(group.DisplayName);

// All groups including transitive memberships
foreach (var group in user.GetAllLDAPGroups())
  Console.WriteLine($"{group.DisplayName} ({group.DistinguishedName})");

Windows impersonation

using System.Security;

// Impersonate with current domain
using (new Impersonation("serviceaccount", "password123")) {
  File.ReadAllText(@"\\server\share\secret.txt");
}

// Impersonate with explicit domain and logon type
using (new Impersonation("MYDOMAIN", "admin", "p@ssw0rd", Impersonation.LogonType.NetworkCleartext)) {
  // Code runs as impersonated user
}
// Original identity is automatically restored

Installation

dotnet add package FrameworkExtensions.DirectoryServices

Dependencies

  • Backports (project reference)
  • Corlib.Extensions (project reference)
  • System.DirectoryServices (framework reference / NuGet)
  • System.DirectoryServices.AccountManagement (framework reference / NuGet)

License

LGPL 3.0 or later - See LICENSE for details

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 is compatible. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net35 is compatible.  net40 is compatible.  net403 was computed.  net45 is compatible.  net451 was computed.  net452 was computed.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 is compatible.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0.43 100 3/2/2026
1.0.0.41 235 7/7/2025
1.0.0.40 283 4/28/2025
1.0.0.33 236 3/10/2025
1.0.0.31 212 12/15/2024
1.0.0.30 210 6/24/2024
1.0.0.29 209 6/17/2024
1.0.0.27 246 6/3/2024
1.0.0.26 210 5/27/2024
1.0.0.25 262 5/6/2024
1.0.0.24 195 4/29/2024
1.0.0.22 261 3/18/2024
1.0.0.21 206 3/5/2024
1.0.0.20 306 12/11/2023
1.0.0.19 255 7/23/2023
1.0.0.18 253 7/21/2023
1.0.0.17 254 7/20/2023
1.0.0.16 277 7/19/2023