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
<PackageReference Include="FrameworkExtensions.DirectoryServices" Version="1.0.0.43" />
<PackageVersion Include="FrameworkExtensions.DirectoryServices" Version="1.0.0.43" />
<PackageReference Include="FrameworkExtensions.DirectoryServices" />
paket add FrameworkExtensions.DirectoryServices --version 1.0.0.43
#r "nuget: FrameworkExtensions.DirectoryServices, 1.0.0.43"
#:package FrameworkExtensions.DirectoryServices@1.0.0.43
#addin nuget:?package=FrameworkExtensions.DirectoryServices&version=1.0.0.43
#tool nuget:?package=FrameworkExtensions.DirectoryServices&version=1.0.0.43
Extensions to DirectoryServices
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 | Versions 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. |
-
.NETCoreApp 3.1
- FrameworkExtensions.Backports (>= 1.0.0.256)
- FrameworkExtensions.Corlib (>= 1.0.2.599)
- System.DirectoryServices (>= 10.0.3)
- System.DirectoryServices.AccountManagement (>= 10.0.3)
-
.NETFramework 3.5
- FrameworkExtensions.Backports (>= 1.0.0.256)
- FrameworkExtensions.Corlib (>= 1.0.2.599)
-
.NETFramework 4.0
- FrameworkExtensions.Backports (>= 1.0.0.256)
- FrameworkExtensions.Corlib (>= 1.0.2.599)
-
.NETFramework 4.5
- FrameworkExtensions.Backports (>= 1.0.0.256)
- FrameworkExtensions.Corlib (>= 1.0.2.599)
-
.NETFramework 4.8
- FrameworkExtensions.Backports (>= 1.0.0.256)
- FrameworkExtensions.Corlib (>= 1.0.2.599)
-
.NETStandard 2.0
- FrameworkExtensions.Backports (>= 1.0.0.256)
- FrameworkExtensions.Corlib (>= 1.0.2.599)
- System.DirectoryServices (>= 10.0.3)
- System.DirectoryServices.AccountManagement (>= 10.0.3)
-
net6.0
- FrameworkExtensions.Backports (>= 1.0.0.256)
- FrameworkExtensions.Corlib (>= 1.0.2.599)
- System.DirectoryServices (>= 6.0.2)
- System.DirectoryServices.AccountManagement (>= 6.0.1)
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 |