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.
Related
I need to fetch active directory records and insert in SQL database. There are approximately 10,000 records. I have used this code:
List<ADUser> users = new List<ADUser>();
DirectoryEntry entry = new DirectoryEntry("LDAP://xyz.com");
ADUser userToAdd = null;
IList<string> dict = new List<string>();
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(&(objectClass=user))";
search.PropertiesToLoad.Add("samaccountname");
search.PageSize = 1000;
foreach (SearchResult result in search.FindAll())
{
DirectoryEntry user = result.GetDirectoryEntry();
if (user != null && user.Properties["displayName"].Value!=null)
{
userToAdd = new ADUser
{
FullName = Convert.ToString(user.Properties["displayName"].Value),
LanId = Convert.ToString(user.Properties["sAMAccountName"].Value)
};
users.Add(userToAdd);
}
}
How can I optimize the above code in terms of speed and space complexity? Can I use traversal in binary tree as Active Directory structure looks similar to binary tree.
The list returned by DirectorySearcher.FindAll() is just a list. So you can't traverse it any better than you already are.
To optimize this, don't use GetDirectoryEntry(). That is doing two things:
Making another network request to AD that is unnecessary since the search can return any attributes you want, and
Taking up memory since all those DirectoryEntry objects will stay in memory until you call Dispose() or the GC has time to run (which it won't till your loop finally ends).
First, add displayName to your PropertiesToLoad to make sure that gets returned too. Then you can access each property by using result.Properties[propertyName][0]. Used this way, every property is returned as an array, even if it is a single-value attribute in AD, hence you need the [0].
Also, if your app is staying open after this search completes, make sure you call Dispose() on the SearchResultCollection that comes out of FindAll(). In the documentation for FindAll(), the "Remarks" section indicates you could have a memory leak if you don't. Or you can just put it in a using block:
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(&(objectClass=user))";
search.PropertiesToLoad.Add("sAMAccountName");
search.PropertiesToLoad.Add("displayName");
search.PageSize = 1000;
using (SearchResultCollection results = search.FindAll()) {
foreach (SearchResult result in results) {
if (result.Properties["displayName"][0] != null) {
userToAdd = new ADUser {
FullName = (string) result.Properties["displayName"][0],
LanId = (string) result.Properties["sAMAccountName"][0]
};
users.Add(userToAdd);
}
}
}
I want to read Parent-GUID attribute from ActiveDirectory.
I have tried below code to read all attributes of AD object from ActiveDirectory.
Code
var dirEntry = new DirectoryEntry(directoryEntryPath);
var directorySearcher = new DirectorySearcher(dirEntry, filter)
{
CacheResults = false,
Tombstone = true,
};
var searchResult = directorySearcher.FindAll(); // get mutiple AD Objects
foreach (SearchResult search in searchResult)
{
foreach (DictionaryEntry prop in search.Properties) // here I get all attributes values But not able to find parent-GUID attribute
{
}
}
Using above code I am able to get all properties of AD Object but I am not able to get value of Parent-GUID attribute.
According to https://learn.microsoft.com/en-us/windows/desktop/adschema/a-parentguid this is a constructed attribute. This means it won't be included in search results. The docs also imply it's there to support DirSync which tells me that it might not be available outside of a DirSync search.
Do you mean something like that?:
string path = "CN=someone,OU=yourOrganizationalUnit,DC=example,DC=com";
DirectoryEntry root = new DirectoryEntry(path);
root.Parent.Guid.ToString(); // this will display you the GUID from the parent of your path
Hope this is what you meant!
Cheers,
ov4rlrd
var searchResult = directorySearcher.FindAll();
foreach(SearchResult search in searchResult)
{
DirectoryEntry de = search.GetDirectoryEntry();
Guid ParentGUID = new Guid((byte[])de.Parent.Properties["objectGUID"][0]);
...
}
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");
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.
How i get the list of active directory user attributes(not of particular user i.e.all attributes) e.g.cn,mail etc. using c#?
If you're on .NET 3.5 and up, you need to check out the classes in System.DirectoryServices.ActiveDirectory for this. You need to look at classes like ActiveDirectorySchema and ActiveDirectorySchemaClass.
You can get hold of the current AD schema by using:
ActiveDirectorySchema currSchema = ActiveDirectorySchema.GetCurrentSchema();
When you have the current schema, you can inspect the various class definitions, e.g.:
ActiveDirectorySchemaClass userSchema = currSchema.FindClass("person");
Once you have that object, you can inspect and enumerate its properties, things like:
MandatoryProperties
OptionalProperties
and so on to get an insight into the AD schema.
DirectoryEntry dir = new DirectoryEntry();
dir.Path = "LDAP://YourActiveDirServername ";
DirectorySearcher sea = new DirectorySearcher(dir);
sea.Filter = "(sAMAccountName=Uname)";
SearchResult seares = sea.FindOne();
StringBuilder str = new StringBuilder();
System.DirectoryServices.ResultPropertyCollection prop = seares.Properties;
ICollection coll = prop.PropertyNames;
IEnumerator enu = coll.GetEnumerator();
while (enu.MoveNext())
{
str.Append(enu.Current + " = " + seares.Properties[enu.Current.ToString()][0] + "\n");
}
Also, take a look at: http://www.codeproject.com/KB/system/everythingInAD.aspx
You could use WMI:
ObjectGetOptions objectGetOptions = new ObjectGetOptions(null, System.TimeSpan.MaxValue, true);
ManagementClass managementClass = new ManagementClass("root\\directory\\LDAP", "ads_user", objectGetOptions);
foreach (PropertyData dataObject in managementClass.Properties)
{
Console.WriteLine(dataObject.Name);
}
While ADExplorer does not list all the available attributes, I have found it a great tool for seeing what goes where.
You can download it from http://technet.microsoft.com/en-us/sysinternals/bb963907.aspx
UserPropertyList = new List<string>();
ActiveDirectorySchema currSchema = ActiveDirectorySchema.GetCurrentSchema();
ICollection Collection = currSchema.FindAllProperties();
IEnumerator Enumerator = Collection.GetEnumerator();
while (Enumerator.MoveNext())
{
UserPropertyList.Add(Enumerator.Current.ToString());
}
The above code will add all search attributes of Active Directory to the UserPropertyList...
Expanding on marc_s's answer here. Here is a complete code example that prints the common name and the actual attribute name.
ActiveDirectorySchema schema = ActiveDirectorySchema.GetCurrentSchema();
ActiveDirectorySchemaClass person = schema.FindClass("user");
foreach( ActiveDirectorySchemaProperty property in person.GetAllProperties() )
{
Console.WriteLine("{0} = {1}", property.CommonName, property.Name);
}
Example output.
Common-Name = cn
Instance-Type = instanceType
NT-Security-Descriptor = nTSecurityDescriptor
Object-Category = objectCategory
Object-Class = objectClass
Object-Sid = objectSid
SAM-Account-Name = sAMAccountName
Account-Expires = accountExpires
...