Ldap Query for all members specific to a Group - c#

I am looking to get a list of users that belong to a specific group 'groupName' is passed into the private method.
DirectoryEntry de = new DirectoryEntry("LDAP://DC=xxxx,DC=net"); // Root Directory //
var ds = new DirectorySearcher(de);
ds.PropertiesToLoad.Add("SAMAccountName");
ds.PropertiesToLoad.Add("member");
ds.Filter = "(&(objectClass=group)(SAMAccountName=" + groupName + "))";
SearchResultCollection AllGroupUsers;
AllGroupUsers = ds.FindAll();
The query returns 3 properties :- adspath, accountName and member.
Member is what I am really after.I access the member property and its values as the following piece of code demonstrates:-
if (AllGroupUsers.Count > 0)
{
ResultPropertyValueCollection values = AllGroupUsers[0].Properties["member"];
but something strange happens here. On the RHS of the equal sign, AllGroupUsers has a value for a specific member as "CN=Mike Schoomaker R,........"
While on the LHS of the equal sign, values has "CN=Mike Schoomaker (OR),....."
I am not quite sure how this is possible... It doesn't happen for each and every value under AllGroupUsers... only thing I know is it happens for external users on the active directory... Can anyone show me how I can fix this and get the actual firstName, LastName and MiddleInitial ?

using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// find a user
using (var group = GroupPrincipal.FindByIdentity(ctx, "groupName"))
{
if (group == null)
{
MessageBox.Show("Group does not exist");
}
else
{
var users = group.GetMembers(true);
foreach (UserPrincipal user in users)
{
//user variable has the details about the user
}
}
}
}

To get a user, not a group you should set DirectoryEntry object and use corresponding properties (e.g. displayName, sn, givenName, initials)
Example:
...
AllGroupUsers = ds.FindAll();
if (AllGroupUsers.Count > 0) {
ResultPropertyValueCollection values = AllGroupUsers[0].Properties["member"];
foreach (string s in values)
{
DirectoryEntry u = new DirectoryEntry("LDAP://" + s);
Console.WriteLine(u.Properties["displayName"].Value);
}
}

Related

ASP.NET LDAP SearchResults Properties returning Byte Array

I am using DirectorySearcher to try and get a list of users in AD to sync them with my App and have copied code from various SO sources, however I am not getting any property values. I'm using the following code:
DirectorySearcher search = new DirectorySearcher();
SearchResultCollection results = null;
string sDefaultOU = "LDAP://...";
DirectoryEntry de = new DirectoryEntry(sDefaultOU);
string userName = "DonaldDuck";
search = new DirectorySearcher
{
SearchRoot = de,
PropertiesToLoad = { "displayname", "sAMAccountName"},
Filter = "(sAMAccountName=" + userName + ")"
};
results = search.FindAll();
foreach (SearchResult result in results)
{
String name;
if (result.Properties["sAMAccountName"].Count > 0)
{
name = result.Properties["sAMAccountName"][0].ToString();
}
}
However, instead of name being equal to to "DonaldDuck", it will be "Byte[10]" or Byte[x] where x is the length.
Can anyone see what I am doing wrong.
If I add a filter it returns one user, so I am pretty sure the code is working in terms of searching
Apparently this issue has been faced by others: LDAP DirectoryEntry SearchResult returns data differently in Windows 8 than Win7
AD is using LDAPv3 encoding the values using UTF8, the solution mentioned in the link above might work for you:
if (result.Properties["sAMAccountName"][0].GetType().IsArray)
{
name = System.Text.Encoding.UTF8.GetString((byte[])result.Properties["sAMAccountName"][0]);
}
else
{
name = result.Properties["sAMAccountName"][0].ToString();
}
instead of
foreach (SearchResult result in results)
{
String name;
if (result.Properties["sAMAccountName"].Count > 0)
{
name = result.Properties["sAMAccountName"][0].ToString();
}
}
try  
foreach (SearchResult result in results)
{
String name;
if (result.Properties["sAMAccountName"].Count > 0)
{
var thisDE=result.GetDirectoryEntry();
name = thisDE.Properties["sAMAccountName"].Value.ToString();
}
}
EDIT: Example
I use this helper method to search my domain (when userDomainAndName="DOMAIN\UserName") but you should be able to tweak it for what you want.
public static DirectoryEntry GetUserDirectoryEntryFromCurrentDomain(string userDomainAndName)
{
var Split = userDomainAndName.Split(#"\\".ToCharArray());
var DomainNetBiosNAme = Split[0];
var UserName = Split[1];
var QueryString = $"(&(objectCategory=person)(objectClass=user)(sAMAccountName={UserName}))";
DirectoryEntry rootDSE = GetDirectoryObject(
"LDAP://" + DomainNetBiosNAme + "/rootDSE");
string domain = "LDAP://" + (string)rootDSE.Properties[
"defaultNamingContext"][0];
var Searcher = new DirectorySearcher(new DirectoryEntry(domain), QueryString);
var Result = Searcher.FindOne();
var tReturn = Result.GetDirectoryEntry();
return tReturn;
}
then to get my users PrimarySMTP address (for example)..
var TheUsersDirectoryEntry=GetUserDirectoryEntryFromCurrentDomain(userDomainAndName);
var TheUsersPrimarySMTP=TheUsersDirectoryEntry.Properties["mail"].Value.ToString();

LDAP Query to getUserGroups

Trying to learn LDAP queries in c# to access get all groups user is assigned to in active directory:
I am using System.DirectoryServices:
Havent tested it yet but from throwing examples together I have got:
//This should return all groups for particular user
public List<string> GetUserGroups(string UserName)
{
//create connection
DirectoryEntry entry = new DirectoryEntry(_lDAPPath);
DirectorySearcher search = new DirectorySearcher(entry);
//Get user with UserName
string query = "(&(objectCategory=User)(objectClass=person)(name=" + UserName + "*))";//(memberOf=*))";
search.Filter = query;
//properties returned by query
search.PropertiesToLoad.Add("memberOf");
search.PropertiesToLoad.Add("name");
System.DirectoryServices.SearchResultCollection mySearchResultColl = search.FindAll();
List<string> userGroups = new List<string>();
//Should only be one user in foreach loop
foreach (SearchResult result in mySearchResultColl)
{
//for user get each group assigned to
foreach (string prop in result.Properties["memberOf"])
{
if (prop.Contains(UserName))
{
//adds group name to string
userGroups.Add(result.Properties["memberOf"][0].ToString());
}
}
}
return userGroups;
}
hoping this works. does anyone see any poss problems? ta
It would be preferable to test your code and indicate any bugs you can't handle before posting. However here is tested code which I have been using for years. It searches by cn i.e. Common Name (user alias)
public static List<string> GetUserGroupDetails(string userName)
{
DirectorySearcher search = new DirectorySearcher();
List<string> groupsList = new List<string>();
search.Filter = String.Format("(cn={0})", userName);
search.PropertiesToLoad.Add("memberOf");
SearchResult result = search.FindOne();
if (result != null)
{
int groupCount = result.Properties["memberOf"].Count;
for (int counter = 0; counter < groupCount; counter++)
{
string s = (string)result.Properties["memberOf"][counter];
groupsList.Add(s);
// _log.DebugFormat("found group for user {0} : {1}", userName, s);
}
}
else
{
_log.Warn("no groups found for user " + userName);
}
return groupsList;
}
Note that the above code also returns email distribution lists for which the user is a member. When I want to exclude these I filter out the entries stating with "dl-".

Get multiple user with similar names from Active Directory using C#

I need to display a list of users (in autocomplete) with similar names from the AD. For example, if I search Arthur and there are 2 people with same name (first name or last name), I should display both the names in the autocomplete. I tried to get the names but it is taking around 2-4 minutes to get the names. I am using the following code:
string[] domainNames = new string[] { "domain1", "domain2" };
List<string> userNames = new List<string>();
string user = string.Empty;
foreach (string domain in domainNames)
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain))
{
GroupPrincipal group = GroupPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, "Domain Users");
if (group != null)
{
foreach (Principal p in group.GetMembers(false))
{
if (p.Name.ToLower().Contains(key.ToLower()))
{
if (!userNames.Contains(p.Name))
userNames.Add(p.Name);
}
}
}
}
}
Any way I can speed up the process? I am already using ajax call.
The cn= filter isn't really valid - there's nothing guaranteeing that format. Instead, look up Ambigous Name Resolution - it's designed for this: http://social.technet.microsoft.com/wiki/contents/articles/22653.active-directory-ambiguous-name-resolution.aspx.
DirectorySearcher ds = new DirectorySearcher();
ds.SearchRoot = new DirectoryEntry("LDAP://" + domain, domain + #"\" + userName, password);
ds.Filter = "(&(objectClass=user)(cn=*" + key + "*))";
ds.PropertyNamesOnly = true;
ds.PropertiesToLoad.Add("name");
ds.PropertiesToLoad.Add("cn");
foreach (SearchResult searchResults in ds.FindAll())
{
foreach (string propertyName in searchResults.Properties.PropertyNames)
{
foreach (Object retEntry in searchResults.Properties[propertyName])
{
var user = retEntry.ToString().Split('/').Where(x => x.Contains("CN")).Select(y => y).FirstOrDefault().Split(',').Where(z => z.Contains("CN")).Select(c => c).FirstOrDefault().Split(',').FirstOrDefault().Split('=')[1];
if(!string.IsNullOrWhiteSpace(user))
userNames.Add(user);
}
}
}
Reduced to 30-40 seconds.

How to find users in AD that belong to a group, and just get their SAMAccountName, and SID?

I just want a user to be able to type in a group name in a textbox, and return just their login name and their SID.
So far i have this, and that loads the users in the group but im unsure how to extract the login and SID.
SearchResult result;
DirectorySearcher search = new DirectorySearcher();
search.Filter = String.Format("(cn={0})", txtGroup.Text);
search.PropertiesToLoad.Add("member");
search.PropertiesToLoad.Add("cn");
search.PropertiesToLoad.Add("objectGUID");
result = search.FindOne();
StringBuilder userNames = new StringBuilder();
if (result != null)
{
for (int counter = 0; counter <
result.Properties["member"].Count; counter++)
{
string user = (string)result.Properties["member"][counter];
userNames.AppendLine(user);
}
}
lblResults.Text = userNames.ToString();
The propertie wich contains SID is called objectSid, and the propertie wich contain th login is sAMAccountName for the NT4 compatible version and userPrincipalName. You'd better work with #Virkkunen advice.
static void Main(string[] args)
{
/* Connection to Active Directory
*/
DirectoryEntry deBase = new DirectoryEntry("LDAP://192.168.183.138:389/dc=societe,dc=fr", "administrateur", "pwd");
/* Directory Search
*/
DirectorySearcher dsLookForGrp = new DirectorySearcher(deBase);
dsLookForGrp.Filter = String.Format("(cn={0})", "yourgroup");
dsLookForGrp.SearchScope = SearchScope.Subtree;
dsLookForGrp.PropertiesToLoad.Add("distinguishedName");
SearchResult srcGrp = dsLookForGrp.FindOne();
/* Directory Search
*/
DirectorySearcher dsLookForUsers = new DirectorySearcher(deBase);
dsLookForUsers.Filter = String.Format("(&(objectCategory=person)(memberOf={0}))", srcGrp.Properties["distinguishedName"][0]);
dsLookForUsers.SearchScope = SearchScope.Subtree;
dsLookForUsers.PropertiesToLoad.Add("objectSid");
dsLookForUsers.PropertiesToLoad.Add("userPrincipalName ");
dsLookForUsers.PropertiesToLoad.Add("sAMAccountName");
SearchResultCollection srcLstUsers = dsLookForUsers.FindAll();
foreach (SearchResult sruser in srcLstUsers)
{
Console.WriteLine("{0}", sruser.Path);
SecurityIdentifier sid = new SecurityIdentifier((byte[]) sruser.Properties["objectSid"][0], 0);
Console.WriteLine(sid.ToString());
foreach (string property in sruser.Properties.PropertyNames)
{
Console.WriteLine("\t{0} : {1} ", property, sruser.Properties[property][0]);
}
}
}
I think it would work better if you reverse your query:
(&(objectClass=user)(memberOf={0}))
This way you'll directly get back a list of users by using FindAll. Don't forget to add sAMAccountName etc into PropertiesToLoad.

How can you find a user in active directory from C#?

I'm trying to figure out how to search AD from C# similarly to how "Find Users, Contacts, and Groups" works in the Active Directory Users and Computers tool. I have a string that either contains a group name, or a user's name (usually in the format firstname middleinitial [if they have one] lastname, but not always). Even if I do a seperate query for groups vs. users, I can't come up with a way to search that captures most user accounts. The Find Users, Contacts, and Groups tool brings them back almost every time. Anyone have any suggestions?
I already know how to use the DirectorySearcher class, the issue is that I can't find a query that does what I'd like. Neither cn nor samaccount name has anything to do with the user's name in this, so I'm unable to search on those. Splitting things up and searching on sn and givenName doesn't catch anywhere near as much as that tool does.
Are you on .NET 3.5 ? If so - AD has great new features in .NET 3.5 - check out this article Managing Directory Security Principals in .NET 3.5 by Ethan Wilanski and Joe Kaplan.
One of the big new features is a "PrincipalSearcher" class which should greatly simplify finding users and/or groups in AD.
If you cannot use .NET 3.5, one thing that might make your life easier is called "Ambiguous Name Resolution", and it's a little known special search filter that will search in just about any name-related attribute all at once.
Specify your LDAP search query like this:
searcher.Filter = string.Format("(&(objectCategory=person)(anr={0}))", yourSearchTerm)
Also, I would recommend filtering on the "objectCategory" attribute, since that's single-valued and indexed by default in AD, which is a lot faster than using "objectClass".
Marc
System.DirectoryServices has two namespaces...DirectoryEntry and DirectorySearcher.
More info on the DirectorySearcher here:
http://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.aspx
You can then use the Filter property to filter by Group, user etc...
So if you wanted to filter by account name you would set the .Filter to:
"(&(sAMAccountName=bsmith))"
and run the FilterAll method. This will return a SearchResultCollection that you can loop through and pull information about the user.
You need to build the search string based on how you're looking for the user.
using (var adFolderObject = new DirectoryEntry())
{
using(var adSearcherObject = new DirectorySearcher(adFolderObject))
{
adSearcherObject.SearchScope = SearchScope.Subtree;
adSearcherObject.Filter = "(&(objectClass=person)(" + userType + "=" + userName + "))";
return adSearcherObject.FindOne();
}
}
userType should either be sAMAccountName or CN depending on how the username is formatted.
ex:
firstname.lastname (or flastname) will usually be the sAMAccountName
FirstName LastName will usually be the CN
public DirectoryEntry Search(string searchTerm, string propertyName)
{
DirectoryEntry directoryObject = new DirectoryEntry(<pathToAD>);
foreach (DirectoryEntry user in directoryObject.Children)
{
if (user.Properties[propertyName].Value != null)
if (user.Properties[propertyName].Value.ToString() == searchTerm)
return user;
}
return null;
}
To add onto Miyagi's answer....
Here's a filter/query to apply to DirectorySearcher
DirectorySearcher ds = new DirectorySearcher();
ds.Filter = "samaccountname=" + userName;
SearchResult result = ds.FindOne();
Got this from the Joe Kaplan and Ethan Wilansky Article
Use this Using (from referencing the System.DirectoryServices.AccountManagement dll):
using System.DirectoryServices.AccountManagement;
private bool CheckUserinAD(string domain, string username)
{
PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, domain);
UserPrincipal user = new UserPrincipal(domainContext);
user.Name = username;
PrincipalSearcher pS = new PrincipalSearcher();
pS.QueryFilter = user;
PrincipalSearchResult<Principal> results = pS.FindAll();
if (results != null && results.Count() > 0)
return true;
return false;
}
The other answers were poorly described, didn't describe how to implement them, and most gave the wrong filter properties. You don't even need to use .Filter -- you can just assign your properties (last name = .Surname, first name = .GivenName) to a UserPrincipal object, then search on that object using a PrincipalSearcher in whatever event that triggers the search:
string firstName = txtFirstName.Text;
string lastName = txtLastName.Text;
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
UserPrincipal up = new UserPrincipal(ctx);
if (!String.IsNullOrEmpty(firstName))
up.GivenName = firstName;
if (!String.IsNullOrEmpty(lastName))
up.Surname = lastName;
PrincipalSearcher srch = new PrincipalSearcher(up);
srch.QueryFilter = up;
I'm assuming you have textboxes for First and Last Name to get it, with IDs/Names of txtFirstName and txtLastName. Note that if you do not have a value in the property you are looking for, do not add it to the UserPrincipal, or it will cause an exception. That's the reason for the checks I included, above.
You then do a .FindAll on srch to get search results into a PrincipalSearchResult collection of Principal objects:
using (PrincipalSearchResult<Principal> results = srch.FindAll())
{
if (results != null)
{
int resultCount = results.Count();
if (resultCount > 0) // we have results
{
foreach (Principal found in results)
{
string username = found.SamAccountName; // Note, this is not the full user ID! It does not include the domain.
}
}
}
}
Note that results won't be null even if its .Count() is 0, and why both checks are there.
You iterate using that foreach to get the properties you need, and this answers the question of how to find a user in AD using C#, but note you can only get to a few properties using the Principal object, and if I reached this question through Google (as I did), I would be very disheartened. If you find that's all you need - great, you're done! But in order to get the rest (and rest my own conscience), you have to dive down, and I'll describe how to do that.
I found you can't just use that username I put above, but you have to get the whole DOMAIN\doej kind of name. This is how you do that. Instead, put this in that foreach loop, above:
string userId = GetUserIdFromPrincipal(found);
and use this function:
private static string GetUserIdFromPrincipal(Principal prin)
{
string upn = prin.UserPrincipalName;
string domain = upn.Split('#')[1];
domain = domain.Substring(0, domain.IndexOf(".YOURDOMAIN"));
// "domain" will be the subdomain the user belongs to.
// This may require edits depending on the organization.
return domain + #"\" + prin.SamAccountName;
}
Once you have that, you can call this function:
public static string[] GetUserProperties(string strUserName)
{
UserPrincipal up = GetUser(strUserName);
if (up != null)
{
string firstName = up.GivenName;
string lastName = up.Surname;
string middleInit = String.IsNullOrEmpty(up.MiddleName) ? "" : up.MiddleName.Substring(0, 1);
string email = up.EmailAddress;
string location = String.Empty;
string phone = String.Empty;
string office = String.Empty;
string dept = String.Empty;
DirectoryEntry de = (DirectoryEntry)up.GetUnderlyingObject();
DirectorySearcher ds = new DirectorySearcher(de);
ds.PropertiesToLoad.Add("l"); // city field, a.k.a location
ds.PropertiesToLoad.Add("telephonenumber");
ds.PropertiesToLoad.Add("department");
ds.PropertiesToLoad.Add("physicalDeliveryOfficeName");
SearchResultCollection results = ds.FindAll();
if (results != null && results.Count > 0)
{
ResultPropertyCollection rpc = results[0].Properties;
foreach (string rp in rpc.PropertyNames)
{
if (rp == "l") // this matches the "City" field in AD properties
location = rpc["l"][0].ToString();
if (rp == "telephonenumber")
phone = FormatPhoneNumber(rpc["telephonenumber"][0].ToString());
if (rp == "physicalDeliveryOfficeName")
office = rpc["physicalDeliveryOfficeName"][0].ToString();
if (rp == "department")
dept = rpc["department"][0].ToString();
}
}
string[] userProps = new string[10];
userProps[0] = strUserName;
userProps[1] = firstName;
userProps[2] = lastName;
userProps[3] = up.MiddleName;
userProps[4] = middleInit;
userProps[5] = email;
userProps[6] = location;
userProps[7] = phone;
userProps[8] = office;
userProps[9] = dept;
return userProps;
}
else
return null;
}
/// <summary>
/// Returns a UserPrincipal (AD) user object based on string userID being supplied
/// </summary>
/// <param name="strUserName">String form of User ID: domain\username</param>
/// <returns>UserPrincipal object</returns>
public static UserPrincipal GetUser(string strUserName)
{
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain);
try
{
UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, strUserName);
return oUserPrincipal;
}
catch (Exception ex) { return null; }
}
public static string FormatPhoneNumber(string strPhoneNumber)
{
if (strPhoneNumber.Length > 0)
// return String.Format("{0:###-###-####}", strPhoneNumber); // formating does not work because strPhoneNumber is a string and not a number
return Regex.Replace(strPhoneNumber, #"(\d{3})(\d{3})(\d{4})", "$1-$2-$3");
else
return strPhoneNumber;
}
Note that the FormatPhoneNumber function is for North American numbers. It will take a number it finds (##########) and separate it into ###-###-####.
You can then get the properties like this, back in that foreach loop:
string[] userProps = GetUserProperties(userId);
string office = userProps[8];
But, as a whole solution, you can even add these results into a DataRow column, and return it as part of a DataTable that you could then bind to a ListView or GridView. This is how I did it, sending in a List<string> filled with the properties I needed:
/// <summary>
/// Gets matches based on First and Last Names.
/// This function takes a list of acceptable properties:
/// USERNAME
/// MIDDLE_NAME
/// MIDDLE_INITIAL
/// EMAIL
/// LOCATION
/// PHONE
/// OFFICE
/// DEPARTMENT
///
/// The DataTable returned will have columns with these names, and firstName and lastName will be added to a column called "NAME"
/// as the first column, automatically.
/// </summary>
/// <param name="firstName"></param>
/// <param name="lastName"></param>
/// <param name="props"></param>
/// <returns>DataTable of columns from "props" based on first and last name results</returns>
public static DataTable GetUsersFromName(string firstName, string lastName, List<string> props)
{
string userId = String.Empty;
int resultCount = 0;
DataTable dt = new DataTable();
DataRow dr;
DataColumn dc;
// Always set the first column to the Name we pass in
dc = new DataColumn();
dc.DataType = System.Type.GetType("System.String");
dc.ColumnName = "NAME";
dt.Columns.Add(dc);
// Establish our property list as columns in our DataTable
if (props != null && props.Count > 0)
{
foreach (string s in props)
{
dc = new DataColumn();
dc.DataType = System.Type.GetType("System.String");
if (!String.IsNullOrEmpty(s))
{
dc.ColumnName = s;
dt.Columns.Add(dc);
}
}
}
// Start our search
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
UserPrincipal up = new UserPrincipal(ctx);
if (!String.IsNullOrEmpty(firstName))
up.GivenName = firstName;
if (!String.IsNullOrEmpty(lastName))
up.Surname = lastName;
PrincipalSearcher srch = new PrincipalSearcher(up);
srch.QueryFilter = up;
using (PrincipalSearchResult<Principal> results = srch.FindAll())
{
if (results != null)
{
resultCount = results.Count();
if (resultCount > 0) // we have results
{
foreach (Principal found in results)
{
// Iterate results, set into DataRow, add to DataTable
dr = dt.NewRow();
dr["NAME"] = found.DisplayName;
if (props != null && props.Count > 0)
{
userId = GetUserIdFromPrincipal(found);
// Get other properties
string[] userProps = GetUserProperties(userId);
foreach (string s in props)
{
if (s == "USERNAME")
dr["USERNAME"] = userId;
if (s == "MIDDLE_NAME")
dr["MIDDLE_NAME"] = userProps[3];
if (s == "MIDDLE_INITIAL")
dr["MIDDLE_INITIAL"] = userProps[4];
if (s == "EMAIL")
dr["EMAIL"] = userProps[5];
if (s == "LOCATION")
dr["LOCATION"] = userProps[6];
if (s == "PHONE")
dr["PHONE"] = userProps[7];
if (s == "OFFICE")
dr["OFFICE"] = userProps[8];
if (s == "DEPARTMENT")
dr["DEPARTMENT"] = userProps[9];
}
}
dt.Rows.Add(dr);
}
}
}
}
return dt;
}
You would call this function like this:
string firstName = txtFirstName.Text;
string lastName = txtLastName.Text;
List<string> props = new List<string>();
props.Add("OFFICE");
props.Add("DEPARTMENT");
props.Add("LOCATION");
props.Add("USERNAME");
DataTable dt = GetUsersFromName(firstName, lastName, props);
The DataTable will be filled with those columns, and a NAME column as the first column, that will have the user's actual .DisplayName from AD.
Note: You must reference System.DirectoryServices and System.DirectoryServices.AccountManagement, System.Text.RegularExpressions, System.Data to use all this.
HTH!
The code I were looking for in this post was:
string uid = Properties.Settings.Default.uid;
string pwd = Properties.Settings.Default.pwd;
using (var context = new PrincipalContext(ContextType.Domain, "YOURDOMAIN", uid, pwd))
{
using (UserPrincipal user = new UserPrincipal(context))
{
user.GivenName = "*adolf*";
using (var searcher = new PrincipalSearcher(user))
{
foreach (var result in searcher.FindAll())
{
DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
Console.WriteLine("First Name: " + de.Properties["givenName"].Value);
Console.WriteLine("Last Name : " + de.Properties["sn"].Value);
Console.WriteLine("SAM account name : " + de.Properties["samAccountName"].Value);
Console.WriteLine("User principal name: " + de.Properties["userPrincipalName"].Value);
Console.WriteLine("Mail: " + de.Properties["mail"].Value);
PrincipalSearchResult<Principal> groups = result.GetGroups();
foreach (Principal item in groups)
{
Console.WriteLine("Groups: {0}: {1}", item.DisplayName, item.Name);
}
Console.WriteLine();
}
}
}
}
Console.WriteLine("End");
Console.ReadLine();
It seems that wildcard for any character is Asterisk (*). That's why:
user.GivenName = "*firstname*";
Read more in Microsoft documentation

Categories