I am trying to access the names of all users in a specific folder, and i cannot find out how to do this. So far I can only search the entire active directory and limit my filter options but this is not enough. This is what I have so far:
DirectoryEntry dir = new DirectoryEntry("LDAP://path.local", "username", "password");
string filter = "(&(objectCategory=person)(objectClass=user);(!userAccountControl:1.2.840.113556.1.4.803:=2)(c=CA))";
string[] propertiesToLoad = new string[1] { "name" };
DirectorySearcher searcher = new DirectorySearcher(dir, filter, propertiesToLoad);
SearchResultCollection results = searcher.FindAll();
List<string> usernames = new List<string>();
foreach (SearchResult result in results)
{
string name = (string)result.Properties["name"][0];
if (name != null)
usernames.Add(name);
}
How would i go about searching for a specific file in the active directory, say if the path was Buisness\Canada\Users?
Ok, using Directories, you should not talk about folders, but OrganizationaUnit (OU).
So here is your vision :
And here (using ADSIEDIT.MSC) is the LDAP vision :
So the path to the MonOU folder is :
OU=MonOU,DC=SILOGIX-ESS01,DC=local
So the code to start your search begining this folder is :
DirectoryEntry dir = new DirectoryEntry("LDAP://path.local/OU=MonOU,DC=SILOGIX-ESS01,DC=local", "username", "password");
string filter = "(&(objectCategory=person)(objectClass=user);(!userAccountControl:1.2.840.113556.1.4.803:=2)(c=CA))";
string[] propertiesToLoad = new string[1] { "name" };
DirectorySearcher searcher = new DirectorySearcher(dir, filter, propertiesToLoad);
SearchResultCollection results = searcher.FindAll();
List<string> usernames = new List<string>();
foreach (SearchResult result in results)
{
string name = (string)result.Properties["name"][0];
if (name != null)
usernames.Add(name);
}
That's not all, you should also configure the scope of your search using :
searcher.SearchScope = SearchScope.Subtree;
Have a look to the 3 volues of SearchScope.
Last thing in a production context, you should write in your search the attributes you want to retreive (like in a SQL query) in order to be sure to retreive those you want and not to retreive too much (performance).
searcher.PropertiesToLoad.Add("cn");
searcher.PropertiesToLoad.Add("objectSid");
If your domain is called contoso.com and you want to search the path mentioned, you'd set this line like this:
DirectoryEntry dir = new DirectoryEntry("LDAP://OU=Users,OU=Canada,OU=Business,DC=contoso,DC=com", "username", "password");
Related
I can successfully get a complete list of all AD Attributes with the following code (including things like extensionAttribute1 - 15)
// get whatever attributes are available
List<string> allAttributes = new List<string>();
var context = new DirectoryContext(DirectoryContextType.Forest, "mydomain.com");
using (var schema = System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema.GetSchema(context)) {
var userClass = schema.FindClass("user");
foreach (ActiveDirectorySchemaProperty property in userClass.GetAllProperties()) {
allAttributes.Add(property.Name);
}
}
However, when I retrieve a user account with the following code, most of these attributes (especially the extensionAttributes) are not present:
SearchResultCollection results;
DirectoryEntry de = new DirectoryEntry("LDAP://RootDSE");
DirectorySearcher ds = new DirectorySearcher("LDAP://" + de.Properties["defaultNamingContext"][0].ToString());
ds.Filter = "(&(objectCategory=User)(objectClass=person))";
results = ds.FindAll();
foreach (SearchResult sr in results) {
Console.WriteLine(sr.Properties["extensionAttribute1"][0].ToString()); // == null
}
What am I doing wrong?
most of these attributes (especially the extensionAttributes) are not present
That is normal. Attributes are only returned if they have a value. If an attribute does not have a value, it is not returned at all.
I'd like to search my active directory for all users that belong to a particular physicalDeliveryOfficeName (LDAP) and store them into an array of type SearchResult. Can I do this with a DirectorySearcher filter? Or is there a better approach?
I'm using asp.net, visual c#. Thanks!
Using the DirectorySeacher class, your query could be
(&(objectClass=user)(physicalDeliveryOfficeName=Kalkutta))
where objectClass=user to get only user entries and physicalDeliveryOfficeName=Kalkutta is your query for an office.
DirectoryEntry entry = new DirectoryEntry("LDAP://...");
DirectorySearcher search = new DirectorySearcher(entry)
{
SearchScope = SearchScope.Subtree,
Filter = "(&(objectClass=user)(physicalDeliveryOfficeName=Kalkutta))"
};
search.PropertiesToLoad.Add("cn");
SearchResultCollection result = search.FindAll();
foreach (SearchResult r in result)
Response.Write(r.Properties["cn"][0]);
I'm trying to get Home Directory attribute value from active directory..
I used the following code:
public static void GetExchangeServerByWwidLdap(string wwid)
{
var exchange = string.Empty;
using (var ds = new DirectorySearcher())
{
ds.SearchRoot = new DirectoryEntry("GC:something");
ds.SearchScope = SearchScope.Subtree;
//construct search filter
string filter = "(&(objectclass=user)(objectcategory=person)";
filter += "(employeeid=" + wwid + "))";
ds.Filter = filter;
string[] requiredProperties = new string[] { "homeDirectory", "homemta" };
foreach (String property in requiredProperties)
ds.PropertiesToLoad.Add(property);
SearchResult result = ds.FindOne();
}
}
When I check result object data, I'm seeing only 2 values: "homemta" and "adspath".
Where is the "homeDirectory" value?
I entered AD website and searched the same values for same users - through the website I can see the all the data I searched for so I assuming that I have code issue somewhere.
What am I doing wrong?
You're trying to retrieve homeDirectory from global catalog.
It’s not there.
You can e.g. bind to the user by ADsPath property (i.e. “LDAP://…” string), then query the homeDirectory attribute of that user.
Or, if you only have a single domain, you can search within that domain instead of searching the GC. In this case you'll be able to retrieve all the properties you want.
I've an Active Directory with domain myDomain.local, under it there exists a Distribution Group that contains many groups.
How can I read (programmatically) all these subgroups to retrieve a list of their names ?
And how to optimize the query to filter the result so that it just retrieves all the groups that ends with the word Region ?
BTW, I'm using C#.Net, ASP.Net and sharepoint, and i'm not experienced with AD.
If you're on .NET 3.5 (or can upgrade to it), you can use this code using the System.DirectoryServices.AccountManagement namespace:
// create the "context" in which to operate - your domain here,
// as the old-style NetBIOS domain, and the container where to operate in
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "YOURDOMAIN", "cn=Distribution Group,dc=YourDomain,dc=local");
// define a "prototype" - an example of what you're searching for
// Here: just a simple GroupPrincipal - you want all groups
GroupPrincipal prototype = new GroupPrincipal(ctx);
// define a PrincipalSearcher to find those principals that match your prototype
PrincipalSearcher searcher = new PrincipalSearcher(prototype);
// define a list of strings to hold the group names
List<string> groupNames = new List<string>();
// iterate over the result of the .FindAll() call
foreach(var gp in searcher.FindAll())
{
// cast result to GroupPrincipal
GroupPrincipal group = gp as GroupPrincipal;
// if everything - grab the group's name and put it into the list
if(group != null)
{
groupNames.Add(group.Name);
}
}
Does that satisfy your needs?
For more info on the System.DirectoryServices.AccountManagement namespace, read the Managing Directory Security Principals in the .NET Framework 3.5 article in MSDN magazine.
Here's the solution I made; for those who are interested:
public ArrayList getGroups()
{
// ACTIVE DIRECTORY AUTHENTICATION DATA
string ADDomain = "myDomain.local";
string ADBranchsOU = "Distribution Group";
string ADUser = "Admin";
string ADPassword = "password";
// CREATE ACTIVE DIRECTORY ENTRY
DirectoryEntry ADRoot
= new DirectoryEntry("LDAP://OU=" + ADBranchsOU
+ "," + getADDomainDCs(ADDomain),
ADUser,
ADPassword);
// CREATE ACTIVE DIRECTORY SEARCHER
DirectorySearcher searcher = new DirectorySearcher(ADRoot);
searcher.Filter = "(&(objectClass=group)(cn=* Region))";
SearchResultCollection searchResults = searcher.FindAll();
// ADDING ACTIVE DIRECTORY GROUPS TO LIST
ArrayList list = new ArrayList();
foreach (SearchResult result in searchResults)
{
string groupName = result.GetDirectoryEntry().Name.Trim().Substring(3);
list.Add(groupName);
}
return list;
}
public string getADDomainDCs(string ADDomain)
{
return (!String.IsNullOrEmpty(ADDomain))
? "DC=" + ADDomain.Replace(".", ",DC=")
: ADDomain;
}
I have some code that queries Active Directory to verify user existence. I am trying to verify a long list of about 1300 ids. I've tried several methods to verify if a user account (LINQ to AD, DirectorySearcher (with and without a parent DirectoryEntry) and also a DirectoryEntry that links to the WinNT:// path). Every time it will come back and say that several users do not exist. If I hardcode their userids in the code and execute for individually, it validates existence. If I try and do it in a foreach loop, I get several false negatives.
Here's the code I am using right now..
static string[] userIDs = new string[] "user1","user2","user3","user4","user5","user6","user7","user8"...,"user1300"};
List<string> nonExistingUsers = new List<string>();
List<string> ExistingUsers = new List<string>();
foreach (string s in userIDs)
{
DirectorySearcher search = new DirectorySearcher();
search.Filter = String.Format("(SAMAccountName={0})", s);
search.PropertiesToLoad.Add("cn");
DirectorySearcher ds = new DirectorySearcher(de, "(&(objectClass=user)(cn=" + s + "))", new string[] { "Name" }, SearchScope.Subtree);
SearchResultCollection resultCollection = ds.FindAll();
SearchResult result = search.FindOne();
if (result != null)
ExistingUsers.Add(s);
else
nonExistingUsers.Add(s);
}
Any suggestions or reasons why I am getting the false negatives?
Couple of things:
first of all, try using the "anr=" (ambiguous name resolution) in your LDAP filter - it searches several name-related attributes and make searching easier. The UserID might not be part of the actual "common name" (CN=user1)
secondly, use the objectCategory instead of objectClass - the objectCategory is single-valued and indexed and thus a fair bit faster on searches
thirdly: why are you first calling .FindAll() and then .FindOne() on the next line? Doesn't seem really necessary at all....
WinNT:// really is only for backward compatibility and if you need to deal with local computer accounts - try to avoid it whenever possible, it also exposes a lot less properties than LDAP
Here's my code I'd write:
static string[] userIDs = new string[] "user1","user2","user3","user4","user5","user6","user7","user8"...,"user1300"};
DirectoryEntry searchRoot = new DirectoryEntry("LDAP://cn=Users,dc=YourComp,dc=com");
List<string> nonExistingUsers = new List<string>();
List<string> ExistingUsers = new List<string>();
foreach (string s in userIDs)
{
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.SearchScope = SearchScope.Subtree;
search.Filter = string.Format("(&(objectCategory=person)(anr={0}))", s);
SearchResultCollection resultCollection = ds.FindAll();
if(resultCollection != null && resultCollection.Count > 0)
ExistingUsers.Add(s);
else
nonExistingUsers.Add(s);
}
Does that work in your scenario??
Also, if you're using .NET 3.5 or higher, things got a lot easier - see:
Managing Directory Security Principals in the .NET Framework 3.5