Geeks With Blogs

Mike H. - Another Geek In Need... WebLog

.Net Directory Services Programming – C# - Part 2

 

Topics Covered

Binding – How to connect to directory services and the flexibility of the bind process.

Properties – Review of the most commonly used AD properties, and a look at a few others.

 

Binding

You will remember in Part 1 that we provided a very simple code example of binding to AD and retrieving the object reference for the user object CN=Mike Hamilton. Here I want to review a little more in detail the binding process.

 

Binding The Default Server

 

Often called serverless binding, or binding to your root context, the following shows the simplest of binding calls:

 

            DirectoryEntry newEntry = new DirectoryEntry();

 

There is one major assumption here: You must be logged into the directory service (or the application you are executing must be) – otherwise the call will fail. This call will return the default server, or default root context – the server that validated your logging onto this network. I will review this in more detail shortly.

Passing The Directory (or ADsPath – we’ll review this in a later Part).

Here we pass the specific server and context that we want to bind to. Borrowing from Part 1 – you’ll remember how we bound to the specific user object.

DirectoryEntry userEntry = new DirectoryEntry(“LDAP://developer.hamilton.com/CN=Mike Hamilton,DC=developer,DC=Hamilton,DC=com”);

 

Here we specify the context of the bind. Note, this can be any server within our domain or even another domain within our directory forest.

 

Passing The Path and Credentials to Bind

 

Here we want to bind to a specific path, and provide credentials that validate we have the permission to do so. This is important as you delve into security in later Parts.

 

DirectoryEntry userEntry = new DirectoryEntry(“LDAP://developer.hamilton.com/CN=Mike Hamilton,DC=developer,DC=Hamilton,DC=com”, “<adminAccountName>”,”<adminPassword”);

 

Here you would replace adminAccountName and adminPassword with the actual credentials you want to user. Those can be the administrator account or any account that actually has permissions to perform the binding.

 

Passing The Path, Credentials, and Authentication Type

 

Not only can we bind with specific credentials, but we can also specify the authentication type we wish the directory service to use. For example:

 

DirectoryEntry userEntry = new DirectoryEntry(“LDAP://developer.hamilton.com/CN=Mike Hamilton,DC=developer,DC=Hamilton,DC=com”, “<adminAccountName>”,”<adminPassword”, AuthenticationTypes.Secure);

 

We will review the AuthenticationTypes when we review AuthenticationTypeEnum in our security review.

 

Passing a Native ADSI Object Reference

 

You will get more into this type of binding when you get into security. For now, I am presenting this for an example/reference for future reviews.

 

DirectoryEntry iAdsEntry = new DirectoryEntry(IADSObject);

 

As we move through the different presentations on this topic, we will touch on each of the bindings methods presented, offering examples / benefits of that method.

 

 

Properties in AD

 

I clarify here – AD (Active Directory). I should note that LDAP is LDAP across most directory providers. I emphasize AD here because some of the examples I will use are specific to AD insofar as the default behavior of a property or binding context. I will explain those when applicable, and will make a notation in the example conveying that it is an AD specific property or context.

 

As mentioned previously, AD (and most directory providers) has a hoard of properties that are available to the developer. Here I want to present some of the most common. What is important to note is the syntax to use when referencing a specific property. (You will remember from Part 1 that property names are spelled out using Camel-Case and single names are in lower-case only.)

 

When a user is initially created, that First Name, Last Name, Account Login Name – ever wondered what these were in AD? There are some givens when interacting with these properties – and I want to point those out first.

 

The Account Login Name is written to a few AD properties that cannot be modified via code. There are some things you can do with an AD user object, but one of the most frustrating is renaming or copying to another directory. You can move an object, and of course, delete one – but let’s move forward.

 

When the account is first created, the following properties are assigned the names you provide when creating the account (and this is assuming you created the account with a management tool / snap-in that facilitates user management – like AD Users & Computers (dsa.msc)):

 

  • First Name = givenName
  • Last Name = sn
  • Login Account Name = sAMAccountName, name, dn

 

If you wanted to retrieve these values using LDAP, and following our example in Part 1, we would do something like the following:

 

using System;

using System.DirectoryServices;

 

namespace DirectoryUtility

 

public class Main()

{

DirectoryEntry userEntry = new DirectoryEntry(“LDAP://developer.hamilton.com/CN=Mike Hamilton,OU=Developers,OU=Accounts,DC=developer,DC=hamilton,DC=com”);

 

string loginID = userEntry.Properties[“sAMAccountName”].Value.ToString();

string firstName = userEntry.Properties[“givenName”].Value.ToString();

string lastName = userEntry.Properties[“sn”].Value.ToString();

MessageBox.Show(“Login ID: “+loginID.ToString()+”\r\n Full Name: “+firstName.ToString()+” “+lastName.ToString(),”Results”);

}

 

Yes, this is a rough example, and it does not allow for exception handling. The objective was to show you how to reference just these fields.

 

Here I’ll list a few (I say a few lightly – there are dozens) properties that you will commonly use or need to use:

 

  • sAMAccountName – user ID of the account created (Note, when programmatically creating/adding users – you have control over this field – but not after the object has been added).
  • name – same value as the sAMAccountName property.
  • givenName – First Name of the user.
  • sn – or Sur Name – Last Name of the User
  • displayName – typically, the same as the name, and sAMAccountName
  • userPrincipalName – the same as name, sAMAccountName
  • co – Country
  • mail – single email address value (I’ll demonstrate how we can maintain multiple emails in another Part).
  • telephoneNumber – User’s phone number
  • description – A description of this account
  • userAccountControl – The enumerated property that we’ll use to manage the user’s account – access, password change, locked, and others.
  • wWWHomePage – User’s default homepage –optional.
  • parent – Parent owner object. For example, the name of the OU the user account is in.
  • cn – Cononical – or Common Name – usually the combination of givenName + sn (NOTE: If you have migrated from another system, like NT4 to AD 2000 – this value is the same as the name, sAMAccountName, and displayName – by default, and it cannot be changed)

 

 

How to list and view all properties available with LDAP?

 

The following code snippet shows how to step through the properties associated with a DirectoryEntry object. (NOTE: This code assumes there is a listbox named propertiesListBox on a form that we can add the properties to.)

 

private void PopulateProperties(DirectoryEntry userEntry)

{

if (userEntry!=null)

{

propertiesListBox.Clear();

foreach (string propertyName in userEntry.Properties.PropertyNames)

            propertiesListBox.Items.Add(propertyName);

}}

 

 

SUMMARY

 

I realize that a lot of this is not meat and potatoes yet, but those Parts are coming. I wanted to take the time to introduce some fundamentals because I realize there are a lot of developers out there that have not been introduced to DirectoryServices, and there is a lot to learn!

 

In our next couple of Parts we are going to look at the DirectorySearcher, the other major class in the DirectoryServices namespace, and then we’re going to look at a few basic examples of user / object management. We will start our own solution that will end up in a complete application that will allow you to connect to a directory service, list accounts and objects in that service, add accounts, add groups, and add other specific objects.

Posted on Tuesday, October 4, 2005 7:45 AM .Net Development | Back to top


Comments on this post: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Your articles have been very informative since I'm new to AD programming. Is there a method/way in the System.DirectoryServices to find out which groups a user belongs? Can we also get the data from an ACL for an object to find out which users or groups have access to that object through the API?
Thanks a bunch.
Left by Frank H on Nov 01, 2005 12:34 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Frank, these are good questions. I'll provide a couple of examples below. I was not going to get into ACL's/ACE's until about Part 6 - but I'll try to share a little on that now too.

First - Security Groups. How to tell what groups a user is a member of?

Using the same examples in Part 1 / Part 2 - and assuming that you have created a binding for Mike Hamilton. Now, we'll read through the 'memberOf' property and populate a list box with the groups that Mike Hamilton is a member of...

foreach (string groupName in userEntry.Properties["memberOf"])
groupsListBox.Items.Add(groupName);

That'll populate a list box called groupsListBox with the fully qualified path and name of each security group. And example output is
CN=Administrators,OU=Users,DC=developer,DC=hamilton,DC=com

If you wanted to capture these and only display the friendly name?

string [] groupNames = groupName.Split(new char [] {','});
groupNamesListBox.Items.Add(groupNames[0].SubString(3);

We simply capture a small string array of the parts of the fully qualified path, and assuming that the CN=Administrators s the first entry ([0]), we strip off the CN= and capture just the name in another list box.

Now you want to talk ACL's???

Here we step out of our normal lessons. ACL's are accessed via the IADsUser object. For example, to create an IADs reference - based on our previous examples, I'd

IADsUser iADsUser = (IADsUser)userEntry.NativeObject;

This returns the iADsUser reference and opens the door for additional API access to the object for Mike Hamilton (in this example).

You retrieve the ACL of a directory object through its 'ntSecurityDescriptor' property. For example

securityDescriptor = iADsUser.Invoke("Get", new Object [] {"ntSecurityDesciptor"}) as IADsSecurityDescriptor.

In this case, you 'could' also reference the DirectoryEntry object directly:

securityDescriptor = userEntry.Properties["ntSecurityDescriptor"].Value as IADsSecurityDescriptor;

ACL and ACE's get more involved than just these couple examples - and I was not prepared to get into these yet, but wanted to take a few minutes to share a couple examples. I will be away from home for almost 2 more weeks on my current engagement - and I will try to complete Parts 3 and 4 before then so I can get them posted.

ACL/ACE will not come until closer to the end of the series. After your query however, I may do an addition to the series, addressing security management within AD using more complex IADsUser object methods.
Left by MikeH on Nov 02, 2005 7:25 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Thankyou I have been trying to find the propertiy name to get the user login for about a week.
Left by Phil Bobbett on Nov 11, 2005 6:00 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
hi
As i was finding users of specific groups the code return me Full name of User .. i need to get only employee ids against any specific group
can any one help me please
regards,
Usman
Left by Usman (kiabaat@hotmail.com) on Dec 02, 2005 10:49 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
If I understand correctly, you are able to determine the ["members"] property of a security group - and in doing so, you realized that the complete CN= is returned with the user's full name, correct?

Now, you want to find that user's login ID? (you said employee id's but I'm guessing they're the same.)

If this is the case, simply parse out the full name from the CN=, and you can try a FindOne() on the ["sn"] and ["givenName"] properties, and then read the ["sAMAccountName"] of the object found.

Hope this is helpful.
Left by MikeH on Dec 02, 2005 2:31 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Mike,

I have a project where I have to deal with both asp and asp.net code. I was successful in getting authentication through active directory in the asp.net part of the code with your articles. Do you have info about authenticating users with active directory from asp files? For example, how do we access AD through asp and how can we find out which groups a user belongs to? If you have any links to such articles, that would be great. My search on the net hasn't been that fruitful. Thanks.
Left by Frank H on Dec 06, 2005 2:10 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Interfacing with AD from ASP.

This is a good question, and it brings to light the disadvantages of ASP vs. ASP.Net and the .Net Framework support for AD integration.

But, you CAN interface with AD from your ASP application. How? A little known, not well documented means: You can call LDAP and perform LDAP queries on AD using ADO!!!

First, if you simple Google (without the quotes) "asp ldap" you will see a lot of stuff and some decent examples on how to do this. I was not going to cover ADO connectivity in my series on Directory Services Programming because I am focusing on the System.DirectoryServices and its classes, and ADO connectivity is not necessary.

Examples? One I found is pretty decent and very straight forward - and it's straight ASP:

<%
Set con = Server.CreateObject("ADODB.Connection")
con.Provider = "ADsDSOObject"
con.Open "Active Directory Provider"
Set Com = CreateObject("ADODB.Command")
Set Com.ActiveConnection = con
Com.CommandText = "select name, sAMAccountName from 'LDAP://developer.hamilton.com/OU=Accounts,OU=Developers,DC=developer,DC=hamilton,DC=com' WHERE objectCategory='person'"
Set rs = Com.Execute
%>

This would return a recordset containing the "name" and "sAMAccountName" properties for all users in the OU=Developers OU.

Yes, there is more to research, but hopefully this will give you 1) encouragement that there is help!!!, and 2) some direction.

Please forgive any typos
Left by MikeH on Dec 11, 2005 9:43 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi, I am new on AD.
I tried out the codes, but the the result I got is someting not I expected. here's my codes:
Public Function GetUserDetails(ByVal domain As String, ByVal username As String, ByVal pwd As String) As String
Dim domainAndUsername As String = domain + "\" & username
Dim UserEntry As DirectoryEntry = New DirectoryEntry(_path, domainAndUsername, pwd)
Dim propertyName As String
Dim info As String
Try
For Each propertyName In UserEntry.Properties.PropertyNames
info = info & "<br>" & propertyName & "=" & Convert.ToString(UserEntry.Properties(propertyName).Value())

Next
Catch ex As Exception
Throw ex



End Try
Return info


End Function

the result:

objectClass=System.Object[]
cn=Users
description=Default container for upgraded user accounts
distinguishedName=CN=Users,DC=my,DC=intranet
instanceType=4
whenCreated=4/20/2005 4:00:41 PM
whenChanged=4/20/2005 4:00:41 PM
uSNCreated=System.__ComObject
uSNChanged=System.__ComObject
showInAdvancedViewOnly=False
name=Users
objectGUID=System.Byte[]
systemFlags=-1946157056
objectCategory=CN=Container,CN=Schema,CN=Configuration,DC=my,DC=intranet
isCriticalSystemObject=True
dSCorePropagationData=System.Object[]
nTSecurityDescriptor=System.__ComObject

I am expecting to get User Name and memberOf.. well it's not there.. any wise one out there?
Left by alseet on Dec 27, 2005 11:54 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Thanks for the 2nd part. Could you please post the links to other parts if available?
Also, I couldn't find the property name I was looking for in the list above.
I need to set the user's domain i.e. @my.com
This prop will show on the Accounbt tab of the AD user (user property from AD user management tool), right along the User Logon Name, showing as a drop down list of domains.
I can not seem to be able to populate this in code?
THanks again, Ditro
Left by Ditro on Jan 23, 2006 10:48 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Ditro,

The easiest thing to do if you want to show the user's 'current' domain association is to parse the parent property which should include the full path, including the domain name.

In other words, if you have a directoryentry object called userEntry.

Parse the userEntry.Parent.Name proprety to get the domain name.

Hope that helps.
Left by MikeH on Jan 24, 2006 4:55 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Well, in this case I'm not trying to parse/get the property value, but need to set it.
I tried to set this property/attrib with the name you suggested (Parent.Name) and didn't work.
Otherwords in my c# code:
entry.Properties["sAMAccountName"].Add("Lee.Hamilton");
entry.Properties["Parent.Name"].Add("@my.com");

& I got the error of setting a wrong attribute!

Any idea? Thanks much - Ditro
BTW: are there links to other parts of your article?
Left by Ditro on Jan 24, 2006 2:59 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Ditro,

Try:

entry.Properties["sAMAccountName"].Value = "Lee Hamilton";

and so on.

If you're using the DirectoryEntry object, and not a IADsUser object.

Let me know if that helps.
Left by MikeH on Jan 24, 2006 3:08 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
the code:
entry.Properties["sAMAccountName"].Add("Lee.Hamilton");
works just fine. What I meant is that the property 'Parent.Name' is invalid when I try to set:
entry.Properties["Parent.Name"].Add("@my.com");

I get no such attribute!
Thanks -Ditro
Left by Ditro on Jan 24, 2006 4:11 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Ditro - my apologies, I misunderstood. That is correct, the .Parent is read-only. It is used to determine the parent path.

Are you trying to add a new account to a specific OU? Or to a specific security group?

Please help me understand better what you are trying to do - and please forgive my ignorance.
Left by MikeH on Jan 24, 2006 4:18 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
No problem.
I am adding a new user to an OU and setup email store. Everything works fine, but when I get the user property using AD management tool (AD Users and computers), on the 'Account' tab I notice the domain drop-down set to blank, having to click and set the value (@myserver.com) manually!

If I go ahead and do the adding procedure using this management tool manually, this drop-down is already populated!

Sorry, but thats the best I can describe it.
Still I'm not sure if this is any problem, as the user's established and owns email box/address.

Thanks again -Ditro
Left by Ditro on Jan 24, 2006 4:37 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Ditro - I understand now.

In truth, I'm not sure just 'what' purpose that drop down serves - even though I understand what you're saying.

If you add a user to a domain context, that user belongs to that context - period. I suspect the dsa.msc snap-in may allow you to change it using the drop down, and assuming you're connected to multiple domains (DC's). But I've never worked with this so I can't really tell you one way or another.

I suspect it should be sufficient - once you've added the user to a given DC and within the desired OU - there's nothing more to do - even if this drop down is 'not' necessarily populated when you view it, if that makes any sense?
Left by MikeH on Jan 24, 2006 4:54 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Mike,

Your articles helped me get started with AD programming. Thank you. I'm now able to get the users belonging to a particular group as well as list the groups that a user is part of. My query now is a slightly different one.

How can I determine if a certain Active Directory group is a member of other groups?
Let’s say we have a group in Active Directory called ‘Microsoft Dallas Employees’ which contains the list of employees in Microsoft’s Dallas office. This group in turn belongs to a bigger group called Microsoft Employees. How do I use ‘Microsoft Dallas Employees’ as a search criteria and find out the other groups that this group belongs to?

I'm using ASP.NET 2.0, C# 2.0 and Active Directory 2003

-Thanks

Left by Alan on Feb 15, 2006 5:31 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Alan, this is a good question, and the answer - albeit easy - is not obvious to everyone.

Each AD group has a "memberOf" property that you can check to see what groups that group is a member of!!!

HTH's
Left by MikeH on Feb 15, 2006 5:59 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Thanks Mike!! I'll test it out now.
Left by Alan on Feb 15, 2006 7:55 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hello Mike,

Is it possible to retrieve sorted information from Active Directory? Let's say we need to get all the members of a particular group in AD. How can we get this list of members sorted by their name?

Thanks in advance
Left by Alan on Feb 28, 2006 4:12 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Alan, good question and I should have posted Part 3 of my series by now, but engagements have kept me from even playing Dad as much as I should.

Anyway... Sorting a return / resultset...

The good news is, there is a sorter class that facilitates this.

One of the public properties of the DirectorySearcher class is .Sort.

The SortOption class allows you to specify the property to sort on and the direction of the sort (ascending/descending).

Using Part 2 of my series, and assuming you want to create a DirectorySearcher on the "cn" property (cononical or common name). Your code might look something like:

DirectoryEntry root = new DirectoryEntry();
DirectorySearcher searcher = new DirectorySearcher(root);
searcher.Filter = "(cn=*)"; // Get all names
searcher.PropertiesToLoad.Add("name");
searcher.PropertiesToLoad.Add("mail");
// Now the SortOption....
SortOption sorter = new SortOpion();
sorter.PropertName = "name";
sorter.Direction = SortDirection.Ascending;
searcher.Sort = sorter;

That'll give you an idea - hopefully.

I apologize for not being able to post more of my development work more frequently - I've simply been on the road too much and away too long.

Please feel free to email me again if you need more info...
Left by MikeH on Feb 28, 2006 9:21 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
How can I find AD attributes given only the loginId of the user (using DirectoryServices rather than ADO)?
Thanks for the great articles.
Left by Graeme on Mar 01, 2006 5:02 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Graeme, there are a few approaches to this.

If you are running on the AD box that you know the user is a member of, you can create a default root binding, and then a DirectorySearcher object reference, and search on that name.

DirectoryEntry root = new DirectoryEntry();
DirectorySearcher searcher = new DirectorySearcher(root);
searcher.Filter("CN=<name>");
searcher.FindOne()

This is just a skeleton of the code you'll actually need, but hopefully that'll give you an idea.

Alternatively, your application may not be running on the AD box, but might be on another server and you need to bind to the AD box for that user only. In a case like this you create a DirectoryEntry reference using that user's credentials for the binding (which is one of the overloads for the class)

DirectoryEntry userEntry = new DirectoryEntry("LDAP://<fullyqualifiedservername>","username","password");

and if this call is successful (meaning the user's credentials are valid) then your object reference is specifically for that user in question.

Hope this helps...
Left by MikeH on Mar 01, 2006 10:09 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Thanks a lot Mike. Your help is very much appreciated. I think you should write a book on Active Directory programming with .Net :) It would certainly help a lot of people since there are no books out there on that topic. I'm looking forward to Part 3 of your series here. Thanks again.
Left by Alan on Mar 01, 2006 1:38 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Mike,
I was reading your posts and you have some great examples and answers. I just wanted to say nice job and thanks.
Matt
Left by Matt on Mar 10, 2006 4:36 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi,

Thanks Mike for the great articles, it's been really helpful. I'm having some problems currently trying to add an optional attribute. For example, the msnpAllowDialin attribute is a boolean. I can easily change it's value (from false to true or vice-versa), or clear it. But, when I try to actually set it to true or false (and it's not set for that user), I get an error.

The same code works fine for string attributes. Here's the concerned section of my code:

de2update = new DirectoryEntry(currentPath, user, pwd);

if (setToTrue)
{
// It's a boolean type field and we want it set to true.
de2update.Properties[textBox3.Text].Add(true);
}
else if (setToFalse)
{
// It's a boolean type field and we want it set to false.
de2update.Properties[textBox3.Text].Add(false);
}
else
{
// Not a boolean, just set to the variable setToValue.
de2update.Properties[textBox3.Text].Add(setToValue);
}
de2update.CommitChanges();
de2update.Close();

The error I'm getting is the following:

The requested operation did not satisfy one or more constraints associated with the class of the object.

Thanks for any help,
Martin
Left by Martin on Mar 15, 2006 11:14 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Martin, without being able to step through your code with you I cannot debug the specific issue.

The textBox3.Text seems to 'not' be what you think is 'should' be in the code. The error you are getting basically boils down to your trying to add a value to something that does not exist in the specific context.

You want to set a property of type boolean, but the question is, depending on the contexdt of your directory entry at this point in the code, is that property actually in textBox3.Text?

All I can recommend at this point is stepping through the code and checking the values one step at a time. You might try hard coding the actual property to see if that works - this would allow you to isolate whether it's the casting of the value passed in textBox3.Text.

Sorry I can't be of more specific help...
Left by MikeH on Mar 16, 2006 10:46 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Thanks for your reply Mike.

I have again tested with hard-coded values, with the same results...

// The following yields: The requested operation did not satisfy one or more constraints associated with the class of the object.
de2update.Properties["msnpAllowDialin"].Add(true);

// The following works (value type is a string, not a boolean).
de2update.Properties["telephoneNumber"].Add("123-4567");

I then tried the following:

object [] myTrue = new object[1];
myTrue[0] = true;

de2update.Properties["msnpAllowDialin"].Add(myTrue);

The result is: Unspecified error.

This is easily reproduceable, just try to add a value for an optional attribute which isn't already set. It will work for a string attribute, but not for a boolean!

Thanks,
Martin
Left by Martin on Mar 16, 2006 11:57 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Martin, I have run into similar situations dealing with properties that have no value set - such as trying to write a null or blank string to a property, and I too have run into similar errors.

I would Google the initial "requested operation did not satisfy one or more constraints" error and see if you can run it down. I know a lot is returned on that search, but that is where I would start.

I have been stalled on working on the series I started and anticipate completing more of it this month. Perhaps I will run into more documentation on this issue during that time - and if I do I'll write up something on it.
Left by MikeH on Mar 17, 2006 2:41 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hello Mike,

Is it possible to get the infomation sorted by more than one field. Suppose we need to get the list of all employees sorted by first name first and then by last name. Can you please let me know how to do that?

Thanks in advance
Left by Jijesh on Apr 09, 2006 11:11 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Jijesh, I have been out of state for a couple weeks and apologize for not getting back to you sooner.

You pose a good question - I have not personally tried to handle multiple sort filters before - but I will try to get an answer and post a response for you this week.
Left by MikeH on Apr 16, 2006 1:26 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Jilesh, after some careful review - I cannot provide a sample of using the Sorter object to sort multiple columns of data. What I wound up doing is reading the data into a dataset and used the sort features there to sort the multiple columns.

You can query specifics from AD, filter the returned properties, and fairly well narrow down the scope / amount of data being returned - but the sorter object / class is fairly limited as well.

Sorry I could not be of more help.
Left by MikeH on May 01, 2006 8:41 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi, I am having the same problem here. I am trying to change the Dial-in through VB .Net program.

I tried:
strNewDSAUser.Properties("msNPAllowDialin").Add(True)

and

strNewDSAUser.Properties("msNPAllowDialin").Value = True

Neither is working, and returning any error. I found out that if dial-in = false, it returns 0. I tried
strNewDSAUser.Properties("msNPAllowDialin").Value = 1

that gives an error.
Left by Joseph on May 02, 2006 7:40 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
I am also having errors to create the mailbox,

my code is:

Dim mailbox As CDOEXM.IMailboxStore
mailbox = CType(strNewDSAUser.NativeObject, CDOEXM.IMailboxStore)

The error is like this:

Unable to cast COM object of type 'System.__ComObject' to interface type 'CDOEXM.IMailboxStore'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{25150F41-5734-11D2-A593-00C04F990D8A}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

can you help?
Left by Joseph on May 02, 2006 7:44 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Joseph, I have not done much with Exchange integration and LDAP programming - however this appears that the error has to do with the strNewDSAUser not being instantiated. Have you tried stepping through your code and ensuring that this object reference is valid? I know that on many occasions I have run into something similar and it wound up being the LDAP reference was invalid - it never bound as I thought it did - but it never through an error either.
Left by MikeH on May 03, 2006 4:08 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Mike,
This is great stuff, thank you.
I want to query against a specific "alias" in our Outlook Exchange. I use your above and it works where "cn=<userid>", however I need to find a specific alias. Can you suggest an approach? I tried the DirectorySearcher but to no avail.

Thanks,
EricC
Left by Eric on May 25, 2006 5:12 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Eric, I have not one anything specific with Exchange. If you can give me a sample of the code that is failing, perhaps I can try to help isolate an issue.

My sincere apologies for not being able to respond sooner.
Left by MikeH on May 29, 2006 11:04 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
I think the CDO.EXM error is due to lacking the MS Exchange Admin tools on your system.
Left by Brian Hampson on Jun 01, 2006 6:48 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Mike,

Thank you for the series and you have done a great job answering reader's questions. I am currently working on a project that I need to create a delta file from active directory when certain attributes change. Do you know if there is an easy way to do it? I read some articles about using uSNChange attribute. I just wonder if there is a solution using .net. Thanks in advance!
Left by Jessie on Jun 05, 2006 3:54 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Awesome !!... Saved my day... spent 15 minutes and I am all set.. good stuff...
Left by Boy on Jun 07, 2006 12:51 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
but... how an i get all users from one group?
i was try to
LDAP://domain.net/CN=all,OU=Domain Groups,DC=domain,DC=net

but have a null result
Left by alucky on Jul 13, 2006 4:26 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi alucky,

If you simply want to enumerate through the members of a Group, you can create a binding to that group, then do a 'foreach' through the 'member' property for that group.

So, if I have a security group called AdminUsers in AD, I can do

DirectoryEntry thisGroup = new DirectoryEntry("LDAP://developer.hamilton.com/CN=AdminUsers,DC=developer,DC=hamilton,DC=com");

foreach (string userName in thisGroup.Properties["member"])
{
// Write out your users, or save them from the userName.ToString()...
}

Hope that helps...
Left by MikeH on Jul 13, 2006 5:56 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi,

I am trying to add a value to objectClass property like below:

string sAdminUsername = "cn=" + AdminUserID + "," + msAdminRoot;

string sAdminPassword = AdminPassword;

string sParentConnectString = "LDAP://" + msDomain + ":" + msDefaultPort + "/" + msUserPath;



using (DirectoryEntry oOutreachOU = new DirectoryEntry(sParentConnectString, sAdminUsername, sAdminPassword, AuthenticationTypes.None))

{

// Now you can add users

using(DirectoryEntry oChild = oOutreachOU.Children.Add("CN=" + txtUsername.Text.ToString(), "user"))

{

// Make changes to the created account before applying the changes.

oChild.Properties["uid"].Value = txtUserID.Text.ToString();

oChild.Properties["sn"].Value = txtSecondName.Text.ToString();

oChild.Properties["userPassword"].Value = txtPassword.Text.ToString();



// Added on 8/1/2006

oChild.Properties["objectClass"].Add("UserAuxClass");



oChild.CommitChanges();

}

}



I am getting this exception when I added UserAuxClass to objectClass. Any help

The requested operation did not satisfy one or more constraints associated with the class of the object.

Thank you
Vijay
Left by Vijay on Aug 03, 2006 1:56 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi ViJay,

Have you tried changing the UserAuxClass to just User? I have not tried to add an objectClass type of UserAuxClass so I cannot speak directly to this - yet. I can try to research this more tonight when I get home.

Let me know...
Left by MikeH on Aug 03, 2006 2:13 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Please let meknow how to find the email server by querying ADS using C#
Left by Rocky on Aug 07, 2006 3:28 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
I know this has been asked a couple of times, but there is one issue with your answer. "How do I get all users of a group?" And you answered, just iterate through the "member" property. While this is correct, it's not the full story. More often than not, members of a group are other groups. For example, "Building1 All Users" is a group that ultimately contains all users physically located in Building 1. However, what we really see inside that group are three other groups, "Finance", "Engineering", and "IT" because those three departments are located in that building while some other departments are located in Building 2.

So if I simply iterate over the "member" property, all I get is "Finance", "Engineering", and "IT". Not a single user object to be found. Hopefully you see where I'm going with this.

Is it possible to somehow write a DirectorySearcher filter that filters and returns all "user objects" of a group, even if that group contains groups?

I am able to set my root DirectoryEntry object to my group in question:

DirectoryEntry de = new DirectoryEntry("LDAP://trimblems.net/CN=TMS ECO Notification List,OU=Distribution Lists,OU=Chandler,DC=trimblems,DC=net");

And then if I create a DirectorySearcher with a filter like:

DirectorySearcher s = new DirectorySearcher(de, "(&(ObjectCategory=Person)(ObjectClass=user))");

Doing a .FindAll() returns zero results.

Any help or advice with this would be appreciated.

Thanks,
Kevin
Left by Kevin on Aug 08, 2006 11:36 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Kevin, I apologize for not being able respond sooner. It has been a super busy week.

Now, to pull just the users from that given Group - remove the objectCaategory=Person from your string, and capitalize the User in the objectClass=User - check the actual syntax of your query.

This should easily return all users - and if it does not, again check your syntax in the query.

HTH's...
Left by MikeH on Aug 13, 2006 6:36 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Joseph, and users having difficulty adding a TRUE or FALSE to a field...

I remember now a gig I was on and I was running into the same problem. Interestingly I was able to set it to TRUE by setting it to -1.

HTH's...
Left by MikeH on Aug 13, 2006 6:44 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi,
Plz can you tell me why i am getting this exception
The value for the sort cannot be set.
Actually i want to sort the users in active directory.
Sample code
DirectorySearcher ds = new DirectorySearcher(de);
ds.Sort = new SortOption("length", SortDirection.Descending);
ds.Filter = filterPath;
If i remove the sort line or comment it then it works fine..
My mail id is : ramchandra@ec.is
You can post the information to this id

Its very urgent..
Left by Ramchandra on Oct 23, 2006 10:52 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Ramchandra,

Without seeing more of the code, and understanding what you are doing - it is hard to speak specifically...

Reading through this feed (I aplogize for not having any notes with me) - I found the following:


SortOption sorter = new SortOpion();
sorter.PropertName = "name";
sorter.Direction = SortDirection.Ascending;
searcher.Sort = sorter;

Here you see how the sorter binding is created, a Property defined for the search (I am not familiar with an AD Property called Length as you had), finally a direction is declared and it's bound.

HTH's...
Left by MikeH on Oct 23, 2006 11:49 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
good, where is the link of part 1?
Left by gary on Oct 24, 2006 2:06 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Left by MikeH on Oct 24, 2006 3:17 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Too far behind!!!
getting error:
Error 1 The type or namespace name 'DirectoryEntry' could not be found (are you missing a using directive or an assembly reference?)

I wrote:

DirectoryEntry entry = new DirectoryEntry("LDAP://DC=cts,DC=com", domainAndUsername, "password9!");

try
{
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=113579)";
search.PropertiesToLoad.Add("cn");
search.PropertiesToLoad.Add("description");
SearchResult result = search.FindOne();
Response.Write(result.Properties["cn"][0]);
Response.Write(result.Properties["description"][0]);
}

catch (Exception ex)
{
Response.Write(ex.Message);
Response.Write(ex.StackTrace);
}

Any suggestions?
Left by Meet on Oct 26, 2006 10:09 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hello Meet,

Make sure you have the directives:

using System;

using System.DirectoryServices;

At the beginning of your class.
Left by MikeH on Oct 26, 2006 10:15 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Your tutorial really is a big help to a lot of people. Thank you for posting it.

I am trying to find all of the groups a given user is a member of. The memberof property just returns System.Object[]. I have included my sample code below. Please let me know if you have any suggestions.

private void FindADEntryData()
{
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.Filter = "(&(objectCategory=person) (objectClass=user) (sAMAccountName=" + txtSearchFor.Text.ToString() + "))";
SortOption sorter = new SortOption();
sorter.PropertyName = "sAMAccountName";
sorter.Direction = System.DirectoryServices.SortDirection.Ascending;
deSearch.Sort = sorter;
lstAD.Items.Clear();
int intFirstPass = 0;
SearchResult resEnt = deSearch.FindOne();
if ((resEnt != null) && (intFirstPass == 0))
{
intFirstPass = 1;
DirectoryEntry root = resEnt.GetDirectoryEntry();
lstUserProperties.Items.Clear();
string strAddItem = "";
foreach (string propertyName in resEnt.Properties.PropertyNames)
{
if (root.Properties[propertyName].Value != null)
{
strAddItem = propertyName + ": " + root.Properties[propertyName].Value.ToString();
lstAD.Items.Add(strAddItem);
if (propertyName == "memberof")
lblMessages.Text = root.Properties[propertyName].Value.ToString();
}
else
lstUserProperties.Items.Add(propertyName);
}
}
}
Left by Gikote on Nov 03, 2006 4:04 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Nevermind, I finally realized it was part of an array. Thanks again for the great articles!
Left by Gikote on Nov 03, 2006 5:53 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi,
I use this code to add new user to AD:
string strAccount = "ext12345";
string strUserCN = "abc #123";

deExternalUser = deExternalLDAP.Children.Add("CN=" + strUserCN.Replace("#", @"\#"), "user");
deExternalUser.Properties["SAMAccountName"].Add(strAccount);
strAction = "Commit1: " + strAccount;
deExternalUser.CommitChanges();

strAction = "Commit1a: " + strUserCN;
deExternalUser.InvokeSet("displayname", strUserCN);
strAction = "Commit2: " + strUserCN;
deExternalUser.CommitChanges();

This code works fine on 2 of 3 ADs (I have 3)
but the last one return 8000500 error (COM).
any Idea?
Left by TSH on Dec 04, 2006 10:03 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi TSH,

The error code is a generic one unfortunately - indicating an unhandled / unknown exception.

With that said, I have seen the error when a value is either NULL (like one of your strings is not initialized after all) or the value is blank when it cannot be. Can you debug/step through the code and double check the values?
Left by MikeH on Dec 04, 2006 12:01 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Mike,
I'll check this out. one other thing is the commit timeout. Are you familier on how to do this (when the process failed it take up ot 5 minutes from the commit command to the catch entry).
Left by TSH on Dec 05, 2006 2:57 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
I have been converting to VS 2003 C# code to the VS 2005. One of my projects having the ActiveDs references is throwing 39 warnings.
Googling I see quite some are having the problem but couldnt see any solution they came up with. Is there anything we can do about getting ride of the warnings?
Left by Satish on Apr 10, 2007 10:47 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Satish,

Without seeing what the warnings are specifically, I cannot speak to whether or not - or how to - get rid of them. Warnings are 'better' than errors though. Is your code working?
Left by MikeH on Apr 10, 2007 1:42 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Mike,
Here they are.
Warning 1 The type library importer could not convert the signature for the member 'ADS_OCTET_STRING.lpValue'. CbsSecAD
Warning 2 The type library importer could not convert the signature for the member '__MIDL___MIDL_itf_ads_0000_0002.lpValue'. CbsSecAD
Warning 3 The type library importer could not convert the signature for the member 'ADS_NT_SECURITY_DESCRIPTOR.lpValue'. CbsSecAD
Warning 4 The type library importer could not convert the signature for the member '__MIDL___MIDL_itf_ads_0000_0003.lpValue'. CbsSecAD
Warning 5 The type library importer could not convert the signature for the member 'ADS_PROV_SPECIFIC.lpValue'. CbsSecAD
Warning 6 The type library importer could not convert the signature for the member '__MIDL___MIDL_itf_ads_0000_0004.lpValue'. CbsSecAD
Warning 7 The type library importer could not convert the signature for the member '_ADS_CASEIGNORE_LIST.Next'. CbsSecAD
Warning 8 The type library importer could not convert the signature for the member '_ADS_OCTET_LIST.Next'. CbsSecAD
Warning 9 The type library importer could not convert the signature for the member '_ADS_OCTET_LIST.Data'. CbsSecAD
Warning 10 The type library importer could not convert the signature for the member 'ADS_NETADDRESS.Address'. CbsSecAD
Warning 11 The type library importer could not convert the signature for the member '__MIDL___MIDL_itf_ads_0000_0011.Address'. CbsSecAD
Warning 12 The type library importer could not convert the signature for the member 'ADS_REPLICAPOINTER.ReplicaAddressHints'. CbsSecAD
Warning 13 The type library importer could not convert the signature for the member '__MIDL___MIDL_itf_ads_0000_0012.ReplicaAddressHints'. CbsSecAD
Warning 14 The type library importer could not convert the signature for the member 'ADS_FAXNUMBER.Parameters'. CbsSecAD
Warning 15 The type library importer could not convert the signature for the member '__MIDL___MIDL_itf_ads_0000_0013.Parameters'. CbsSecAD
Warning 16 The type library importer could not convert the signature for the member 'ADS_DN_WITH_BINARY.lpBinaryValue'. CbsSecAD
Warning 17 The type library importer could not convert the signature for the member '__MIDL___MIDL_itf_ads_0000_0015.lpBinaryValue'. CbsSecAD
Warning 18 The type library importer could not convert the signature for the member '_ads_attr_info.pADsValues'. CbsSecAD
Warning 19 The type library importer could not convert the signature for the member 'ads_search_column.pADsValues'. CbsSecAD
Warning 20 The type library importer could not convert the signature for the member '_ads_class_def.ppszMandatoryAttrs'. CbsSecAD
Warning 21 The type library importer could not convert the signature for the member '_ads_class_def.ppszOptionalAttrs'. CbsSecAD
Warning 22 The type library importer could not convert the signature for the member '_ads_class_def.ppszNamingAttrs'. CbsSecAD
Warning 23 The type library importer could not convert the signature for the member '_ads_class_def.ppszSuperClasses'. CbsSecAD
Warning 24 The type library importer could not convert the signature for the member '_ads_vlv.lpContextID'. CbsSecAD
Warning 25 At least one of the arguments for 'IPrivateDispatch.ADSIGetIDsOfNames' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD
Warning 26 At least one of the arguments for 'ITypeInfo.RemoteGetTypeAttr' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD
Warning 27 At least one of the arguments for 'ITypeInfo.RemoteGetFuncDesc' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD
Warning 28 At least one of the arguments for 'ITypeInfo.RemoteGetVarDesc' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD
Warning 29 The type library importer could not convert the signature for the member 'tagARRAYDESC.rgbounds'. CbsSecAD
Warning 30 At least one of the arguments for 'ITypeComp.RemoteBind' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD
Warning 31 The type library importer could not convert the signature for the member 'tagFUNCDESC.lprgscode'. CbsSecAD
Warning 32 The type library importer could not convert the signature for the member 'tagFUNCDESC.lprgelemdescParam'. CbsSecAD
Warning 33 The type library importer could not convert the signature for the member 'tagPARAMDESC.pparamdescex'. CbsSecAD
Warning 34 At least one of the arguments for 'ITypeLib.RemoteGetLibAttr' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD
Warning 35 At least one of the arguments for 'IADsExtension.PrivateGetIDsOfNames' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD
Warning 36 At least one of the arguments for 'IDirectoryObject.GetObjectInformation' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD
Warning 37 At least one of the arguments for 'IDirectoryObject.GetObjectAttributes' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD
Warning 38 At least one of the arguments for 'IDirectorySchemaMgmt.EnumAttributes' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD
Warning 39 At least one of the arguments for 'IDirectorySchemaMgmt.EnumClasses' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate. CbsSecAD

have you seen them?
Left by Satish on Apr 11, 2007 2:03 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
I havent fully tested the functionality but i belive it is working. Infact when I googled about it I read there were no problems with it working as normal. But I do have to remove the warnings. May be supress them but Couldnt go far on that route either.

Thankx upfront.
Left by Satish on Apr 11, 2007 2:05 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Mike,

Didnt know which thread you were gona check so am posting this again here.

Anyway I was thinking may be I should go away with the interop and see if I can just use the system.directoryservices.

The things I do in the code using the interop are: ActiveDs.LargeInteger liMaxAge = domainDE.Properties["MaxPwdAge"].Value as LargeInteger;
maxAge = (((long)(liMaxAge.HighPart) << 32) + (long) liMaxAge.LowPart);
LargeInteger li = userDE.Properties["pwdLastSet"].Value as LargeInteger;
IADsUser nativeUser = (IADsUser)userDE.NativeObject;
pwdLastSet = nativeUser.PasswordLastChanged.ToUniversalTime();
badLogonCount = nativeUser.BadLoginCount

Is there a way to do the same without the activeds reference?

Thank You,
Satish
Left by Satish on Apr 12, 2007 1:18 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Mike, great article! its taken alot of searching to try and find some releveant help.

Im designing a web app and im tring to get "company" from.
My users login and authenticate using the ActiveDirectoryMembershipProvider

I keep getting
System.NullReferenceException was unhandled by user code

also how can i read in the password from the Membership as i dont want to statically set it in the ldap connection string below?


public class UserName
{

private string Xuser_Name;
private string Xuser_Email;
private string Xuser_AccountCreationDate;
private string Xuser_LastLoggedin;
private string Xuser_Provider;
private string Xuser_other;
private string Xuser_property;


public UserName()
{

string partou = "LDAP://DRS.Local/CN=Users,DC=DRS,DC=Local";

Xuser_Name = Membership.GetUser().ToString();
Xuser_Email = Membership.GetUser().Email;

DirectoryEntry de = new DirectoryEntry("LDAP://domain.Local/CN=Users,DC=domain,DC=Local", Xuser_Name,"******", AuthenticationTypes.Secure);

Xuser_property = de.Properties["company"].Value.ToString();

}

public string getUserName()
{
return Xuser_Name;

}

public string getUserEmail()
{
return Xuser_Email;

}


public string getUserProperty()
{
return Xuser_property;

}

}
Left by David on Apr 19, 2007 7:17 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
You articles provided some helpful staring pointers for me. However, I’m wondering if you can help me with a nagging problem I’ve been trying to resolve.

I’m logged into my own computer as part of my company’s AD domain (for example I’m logged in as MYCOMP\myuserid with mypassword).

I writing test code to query a customer’s AD which is on the same network (at, for example, ad.customer.com). There are no trust relationships between those domains—the customer’s domain is simply a stand-alone Domain Controller. They have provided me a user id and password on that AD server and a list of other accounts that I can query for on that server.

I use the user id (e.g. customeruserid) and password (e.g. customerpassword) the customer provided to connect to ad.customer.com using the DirectoryEntry class. Then I create a DirectorySearcher object with the filter set to the user id I need to look up. Right now I’m simply checking that it exists, but eventually I’ll retrieve other properties and use them.

Here’s my VB.NET test code simplified to show just the relevant portions:

Sub Check()
Dim userOkay As Boolean = False
Try
Dim masterUser As DirectoryEntry = New DirectoryEntry( _
"LDAP://ad.customer.com/DC=ad,DC=customer,DC=com", _
"customeruserid", "customerpassword")
If Not masterUser Is Nothing Then
Dim search As DirectorySearcher = _
New DirectorySearcher(masterUser)
search.Filter = "(sAMAccountName=useridtocheck)"
Dim sr As SearchResult = search.FindOne()
If Not sr Is Nothing Then
userOkay = True
Else
Console.WriteLine("User ID not found!")
End If
Else
Console.WriteLine("Can't bind to the server!")
End If
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
If userOkay Then
Console.WriteLine("User ID is okay!")
End If
End Sub

The problem I’m having is that when I run this multiple times and any of customeruserid, customerpassword or useridtocheck are invalid I end up locked out of my company’s domain. In other words I can’t re-login to my own machine using my company’s domain credentials, until the account lockout automatically resets.

Can you help understand why trying to query a totally different AD server should affect my login account in my company’s domain? Is there something else I should be specifying when I create the DirectoryEntry object that will force it to only attempt to connect to my customer’s server and not do anything with the domain that I’m currently logged in using?

Thanks for any help you can give.

Jon
Left by JonH on Apr 19, 2007 10:09 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
I just did some more testing and I end up locked out of my login domain even when all the user ids and passwords are okay. It's like it's saying that "customeruserid" and "customerpassword" are not valid in my company's domain. One other piece of information is that the two user id's are the actually the same. In other words the one the customer set up for me, "customeruserid", is in realtity exactly the same as my user id in my company's domain. So because the passwords are different it's locking me out. But why is it even trying to access my company's AD domain?

Thanks again!
Left by JonH on Apr 19, 2007 10:20 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi David,

I would not use the DirectoryServices API if you're using the ADMembershipProvider - I would use the provider object model.

You can accomplish the same thing - getting the name and email - using DirectoryServices - but the 2 are not the same - if that makes sense?

If your ASP.Net application is doing forms based authentication (FBA), and the provider is the ADMembershipProvider - then stick with that period. If you want to change the provider to either Windows authentication - then it makes sense to use the DirectoryServices API to manage/update/change user accounts.

HTH's...
Left by MikeH on Apr 21, 2007 10:02 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Jon H,

Foremost, you mention that the two AD domains do not have a trust. This would lead me to believe that they are not a part of the same forest. Is this true? If it is, then you will need to designate an account that will run as your process - setup a Service Principal Name (SPN) for that account, and then test the application again.

If there is no trust between the two domains, then it makes sense that you are attempting to connect to this other AD forest, it is resorting to our credentials - and it is locking out your account because there is something not quite right with what you are passing.

Try testing your application on a standalone server - on AD controller/forest - and see if it works fine. That's the first test - then we can discuss staging it to another server, hence the SPN and what is involved there.

Please let me know if I can be of any other help.
Left by MikeH on Apr 21, 2007 10:06 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Can you help me ! I have the same problem!the following:
System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to interface type 'CDOEXM.IMailboxStore'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{25150F41-5734-11D2-A593-00C04F990D8A}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
I will be much gratitude to you for helping me !
Left by FrankLin on Jun 28, 2007 11:22 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi FrainkLin,

I have not done anything specifically with the Exchange interfacing. However, I have seen similar errors in general in DirectoryServices and the error appears to be generic because you have not bound to an instance before referencing it? Or you are not doing the binding correctly.

If you could post your code snipet here - perhaps I could shed more light on it.
Left by MikeH on Jun 29, 2007 6:06 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
string connectionString = "LDAP://domain_name/CN=Users,DC=some,DC=local";

DirectoryEntry de = new DirectoryEntry(connectionString, "domain_name\administrator", "Password", AuthenticationTypes.Secure);


above code throws exception of "An operation error occured"

HELP will be highly appreciated.....!
Left by Gurudatt on Oct 10, 2007 6:13 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Gurudatt,

Without seeing more code and what you are doing, I do not know that I can help with what you provided.

the connectionString = "LDAP:/domain_name/CN=Users,DC=some,DC=local";

would indicate that 'domain_name' is actually some.local - these are the same - so ensure the domain components (DC's) are actually the full domain name.

Also, is there a container under this domain name called Users?

Finally, are you running this code on the same domain? In other words, if you are running it on a local desktop/notebook - even though you're passing the login credentials, if the server is not a member server, it can fail with a non-specific error - which is what appears to be happening.

More code would be helpful.

Left by MikeH on Oct 10, 2007 7:27 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Mike:

Very informative, especially the replies to the posted questions! Hope you've got bandwidth for one more ...

I had some code that was actually working properly -- or so I thought. It was operating in context of an IIS Application Pool running under NT_AUTHORITY\Network Service, and that -- apparently -- was sufficient for authentication to work without me having to supply credentials.

However, for various reasons, we have to run that App Pool under custom credentials. As soon as we did that, we started getting an exception thrown by a Bind() failure.

So I'll have to feed it a userid and a password (this is server stuff, so if there's a way to authenticate differently, I could sure stand to know), but what's not clear to me is why the code worked in the first place:

string GetUpnForDomainName(string domainUserName)
{
string directoryServerName = null;
string rootDomainDc = null;
string samAccountName = null;
string[] ntlmNameParts =
domainUserName.Split(("\\").ToCharArray());
samAccountName = ntlmNameParts[1];

using (DirectoryEntry rootDe = new DirectoryEntry("LDAP://RootDSE"))
{
directoryServerName =
rootDe.Properties["dnsHostName"].Value.ToString();
rootDomainDc =
rootDe.Properties["rootDomainNamingContext"].Value.ToString();

}

string ldapDomainEntryPath =
@"LDAP://" +
directoryServerName + @"/" + rootDomainDc;

using (DirectoryEntry domainEntry =
new DirectoryEntry(ldapDomainEntryPath))
{
using (DirectorySearcher searcher =
new DirectorySearcher(domainEntry))
{
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.Add("userPrincipalName");
searcher.Filter =
"(&(objectClass=user)(samAccountName=" +
samAccountName + "))";

SearchResult userResult = searcher.FindOne();

if (userResult == null)
throw new ArgumentException(
"User {0} not found.", domainUserName);

return userResult.Properties["userPrincipalName"][0].ToString();

}
}
}
Left by Josh on Oct 10, 2007 10:50 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Josh,

Most appPools run by default as the local network service (under Win2K3), and I'm a bit surprised that you had an ASP.Net application that ran this code as that service wihtout issues.

Now, you are running the appPool as a specific service account and you're running into issues binding - this is not uncommon. What is more than likely happening is that the binding is reverting to the specified account - which, from what I'm seeing, will fail, so you have to specify the user/password in the binding call. This by the way, is a better practice.

I am really curious what your environment was like before this that it allowed the application to bind without specific parameters? I say this because the network service, or any local service account, cannot cross borders - or specifically, they cannot run processes on other servers. Specifically, an ASP.Net application that does a directory bind on a DC like in your code - would either have been passing the login - which you indicated it was not - or it was impersonating the local admin account and able to make the code work from there (that's just a guess). I've seen environments where they were able to get the code to work in that context (the appPool was actually impersonating the local admin - 'and' - was a member server).

I don't know if any of this was helpful - but my curiosity is piqued. I've done a lot of DS's programming - and it's often fickle when dealing with multiple servers - and especially when involving ASP.Net applications. To underestand how it was working initially for you would involve more of an understanding of the domain environment, permissions, member servers, etc. - basically more than may be obvious on the surface, if that makes sense?
Left by MikeH on Oct 10, 2007 11:08 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
When I retrieve a list of group members, it is not the same as the list I see in "Active Directory User and Computers." The "Domain Admins" group has 20 entries in ADUC but the code only returns 7. The members are all of type "User" and I cannot see any difference between them. Any ideas?
Left by Carl Baker on Jul 17, 2008 1:10 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Carl... I have been on the road a few weeks and sincerely apologize for not responding sooner. I was hoping you would have had a response by now...

If I understand you correctly, you are not doing a DirectoryEntry dEntry = new DirectoryEntry("searchCriteria"); and retrieving a user, and then looking at the ("memberOf") property for the user - getting the groups a user is a member of.

Instead you're doing a search on the security group proper and looking at the members property? Is that correct? An so, you have 'x' number of user accounts that are in that member group - but only 7 of those appear to be returned in your call? Is that correct?

If so, is it possible the other 'user' accounts are delegate acconts for other services, like SQL Server, BizTalk - or even IIS or MOSS IIS applications that are provisioned as Delegate accounts to run that service? These are not just User accounts if they are delegates as well.

Let me know...
Left by MikeH on Aug 02, 2008 7:12 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Very nice article!
I am just wondering what would be the syntax to update the telephoneNumber property?
Left by Mani on Jan 03, 2009 2:33 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Mani... 'telephoneNumber' is actually just another property - so you can update it just like you would 'sn' or 'name'.

So, for example, I could do

DirectoryEntry de = new DirectoryEntry("LDAP://dev.hamilton.com/CN=Mike Hamilton, DC=dev,DC=hamilton,DC=com");

de.Properties["telephoneNumber"].Value = "555-1212";

and update the value - it's very similar to other directory properties.

Exceptions are usually with things like the email address - which I've blogged about as well. Also review - http://geekswithblogs.net/mhamilton/archive/2006/07/15/85303.aspx for more on directory services work.

Let me know if that helps
Left by MikeH on Jan 03, 2009 3:01 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Your article is very good for about active directory programming.

I have a question about my problem. If I know domain, admin user name and password, then how I authenticate a Active directory user which must belong to a particular group without lock that user on 3 unsuccessful login tries, because that lock policy is set on server.

Thanks
Naeem
Left by Naeem on Apr 01, 2009 4:26 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi Mike,

Great article - very informative.

I have a question that I was hoping you would be able to help with. I have two domains, lets call them ABC and DEF. DEF is a sub domain of ABC. I have a group "B100" which contains users from both domains. I want to be able to pass the user name and get back the list of groups - which I can then check against B101 to see if they are allowed to view a particular web page.

I was hoping that I would be able to use the LDAP of the ABC domain to get permissions for both users. Not surprisingly, the ABC domain user gives me the list without problem but the DEF user does not. I get no groups at all when I pass the username. I have tried to prefix it with the DEF domain but that does not work either.

Can you help?

Here is my code - I create a collection of the groups returned so I can do a whole stack of validation later on.

const string MEMBER_OF_KEY = "memberof";

DirectoryEntry de = null;
DirectorySearcher ds = null;
SearchResultCollection src = null;

try {
de = GetActiveDirectoryRoot();
ds = new DirectorySearcher(de);
ds.Filter = "(samaccountname=" + sUserName + ")";
ds.PropertiesToLoad.Add(MEMBER_OF_KEY);
src = ds.FindAll();
foreach(SearchResult srEntry in src) {
foreach(string sKey in srEntry.Properties.PropertyNames) {
if(sKey == MEMBER_OF_KEY) {
ResultPropertyValueCollection pvc = srEntry.Properties[sKey];
for(int i=0;i < pvc.Count;i++) {
string sGroupText = srEntry.Properties[sKey][i].ToString();
int iCommaIndex = sGroupText.IndexOf(',');
string sGroupName = sGroupText.Substring(3, iCommaIndex - 3);
scActiveDirectoryGroups.Add(sGroupName);
}
}
}
}
}

Thanks Heaps in advance
Left by Jacqui on May 31, 2009 9:50 PM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi...

I need to list the possible value of a property. Is Possible?
If i have a property of permissions, how can i list all possible permissions??

Plz Help
Left by Miguel on Mar 02, 2011 3:03 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
I have been struggling with a strange error while implementing Directory services. On one system, when I create a directory entry object based on IIS (IIS://localhost/W3SVC) and loop through the results using a foreach, a key property "ServerBindings" returns a 'System.Object' value, not the binding information:

------
iisRoot = new DirectoryEntry("IIS://localhost/W3SVC");
....
foreach (DirectoryEntry webSite in iisRoot.Children) {

foreach (PropertyValueCollection prop in webSite.Properties)
{
showme.Text += "\t\t" + prop.PropertyName + ": " + prop.Value + Environment.NewLine;
}
}
...
The results:
ServerAutoStart: True
ServerSize: 1
ServerState: 2
Win32Error: 0
AppPoolId: DefaultAppPool
DefaultDoc: Default.aspx,Default.htm,Default.asp,index.htm,iisstart.htm
KeyType: IIsWebServer
LogPluginClsid: {FF160663-DE82-11CF-BC0A-00AA006111E0}
ServerComment: Default Web Site
ServerBindings: System.Object[]
AllowKeepAlive: True
AppAllowClientDebug: False
AppAllowDebugging: False
AspAllowOutOfProcComponents: True
AspAllowSessionState: True
AspAppServiceFlags: 0
AspBufferingLimit: 4194304
AspBufferingOn: True
AspCalcLineNumber: True
AspCodepage: 0
AspEnableApplicationRestart: True
AspEnableAspHtmlFallback: False
AspEnableChunkedEncoding: True
AspEnableParentPaths: False
AspEnableTypelibCache: True
AspErrorsToNTLog: False
AspExceptionCatchEnable: True
AspExecuteInMTA: 0
AspKeepSessionIDSecure: 0
AspLCID: 2048
AspLogErrorRequests: True
AspMaxDiskTemplateCacheFiles: 2000
AspMaxRequestEntityAllowed: 204800
AspProcessorThreadMax: 25
AspQueueConnectionTestTime: 3
AspQueueTimeout: -1
AspRequestQueueMax: 3000
AspRunOnEndAnonymously: True
AspScriptEngineCacheMax: 250
AspScriptErrorSentToBrowser: True
AspScriptFileCacheSize: 500
AspScriptTimeout: 90
AspSessionMax: -1
AspSessionTimeout: 20
AspTrackThreadingModel: False
AuthFlags: 1
CacheISAPI: True
CGITimeout: 300
ConnectionTimeout: 120
ContentIndexed: True
DirBrowseFlags: 1073741886
LogExtFileFlags: 2199519
LogFilePeriod: 1
LogFileTruncateSize: 20971520
LogType: 1
MaxConnections: -1
PasswordChangeFlags: 6
AnonymousUserName: IUSR_MAN245FS
AnonymousUserPass: evRw$j0#m&T[QC
AspScriptErrorMessage: An error occurred on the server when processing the URL. Please contact the system administrator.
AspScriptLanguage: VBScript
LogOdbcDataSource: HTTPLOG
LogOdbcPassword: sqllog
LogOdbcTableName: InternetLog
LogOdbcUserName: InternetAdmin
AspDiskTemplateCacheDirectory: %windir%\system32\inetsrv\ASP Compiled Templates
LogFileDirectory: C:\WINDOWS\system32\LogFiles
HttpCustomHeaders: X-Powered-By: ASP.NET
HttpErrors: System.Object[]
ScriptMaps: System.Object[]
MaxBandwidth: -1
AdminACL: System.__ComObject
------------------------------
On other systems I woudl get, for ServerBindings something like :80: in the format <ip>:<port>:<header>

is there something configured incorrect on the website (Default WebSite) that causes the System.Object return?

Thanks.
Left by Justin Hull on Mar 18, 2011 8:23 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
i learn C program DOS6.2
Left by "KISHORE".AND.PINCODE="110018" on Jan 11, 2012 3:33 AM

# re: .Net Directory Services Programming - C# - Part 2 - DirectoryEntry Binding and AD Properties
Requesting Gravatar...
Hi,

I need to update the thumnail photo attribute of each employee in the Ldap, I can do the update with code,but the problem i am facing is , logining into the LDAP link and find the DN name for employee on empid base, which i am failing, hoping that you would help me here.
Left by Janardhan on May 02, 2012 6:35 AM

# Great article
Requesting Gravatar...
Thanks a lot. Your article helped me a lot :)
Left by David on Jul 24, 2012 8:13 AM

Your comment:
 (will show your gravatar)


Copyright © Michael J. Hamilton, Sr. | Powered by: GeeksWithBlogs.net