Before .Net managing Active Directory objects is a bit lengthy and you need a good knowledge on the principal store to have your head around on what you want to do. We ususally use the System.DirectoryServices namespace but with .Net 3.5 they introduced System.DirectoryServices.AccountManagement which is manages directory objects independent of the System.DirectoryServices namespace.
So what are the advantages of using this if I have already a library created for the whole AD Methods that System.DirectoryServices exposed? Because everything is really simple in terms of managing a user, computer or group principal and performing queries on the stores are much faster thanks to the Fast Concurrent Bind (FSB) feature which caches the connection which decreases the number of ports used in the process.
I remember I had posted a while back Active Directory Objects and C# which is basically everything regarding AD Methods in terms of Users and Group management and if you see the codebase is a bit lengthy and you need a bit of understanding on setting and getting hex values thats why I ennumerated it. Now I had rewritten it using the System.DirectoryServices.AccountManagement namespace, fucntionalities remain the same but its easier to understand and there are fewer lines.|
The code is divided into several regions but here are the 5 key regions with their methods explained
Validate Methods
- ValidateCredentials – This Method will validate the users credentials.
- IsUserExpired – Checks if the User Account is Expired.
- IsUserExisiting – Checks if user exsists on AD.
- IsAccountLocked – Checks if user account is locked
Search Methods
- GetUser – This will return a UserPrincipal Object if the User Exists
User Account Methods
- SetUserPassword – This Method will set the Users Password
- EnableUserAccount – This Method will Enable a User Account
- DisableUserAccount – This Methoid will Disable the User Account
- ExpireUserPassword – This Method will Force Expire a Users Password
- UnlockUserAccount – This Method will unlocks a User Account
- CreateNewUser – This Method will Create a new User Directory Object
- DeleteUser – This Method will Delete an AD User based on Username.
Group Methods
- CreateNewGroup – This Method will create a New Active Directory Group
- AddUserToGroup – This Method will add a User to a group
- RemoveUserFromGroup – This Method will remove a User from a Group
- IsUserGroupMember – This Method will Validate whether the User is a Memeber of a Group
- GetUserGroups – This Method will return an ArrayList of a User Group Memberships
Helper Methods
- GetPrincipalContext – Gets the base principal context
Now here are the codes
using System; using System.Collections; using System.Text; using System.DirectoryServices.AccountManagement; using System.Data; using System.Configuration; public class ADMethodsAccountManagement { #region Variables private string sDomain = "test.com"; private string sDefaultOU = "OU=Test Users,OU=Test,DC=test,DC=com"; private string sDefaultRootOU = "DC=test,DC=com"; private string sServiceUser = @"ServiceUser"; private string sServicePassword = "ServicePassword"; #endregion #region Validate Methods /// <summary> /// Validates the username and password of a given user /// </summary> /// <param name="sUserName">The username to validate</param> /// <param name="sPassword">The password of the username to validate</param> /// <returns>Returns True of user is valid</returns> public bool ValidateCredentials(string sUserName, string sPassword) { PrincipalContext oPrincipalContext = GetPrincipalContext(); return oPrincipalContext.ValidateCredentials(sUserName, sPassword); } /// <summary> /// Checks if the User Account is Expired /// </summary> /// <param name="sUserName">The username to check</param> /// <returns>Returns true if Expired</returns> public bool IsUserExpired(string sUserName) { UserPrincipal oUserPrincipal = GetUser(sUserName); if (oUserPrincipal.AccountExpirationDate != null) { return false; } else { return true; } } /// <summary> /// Checks if user exsists on AD /// </summary> /// <param name="sUserName">The username to check</param> /// <returns>Returns true if username Exists</returns> public bool IsUserExisiting(string sUserName) { if (GetUser(sUserName) == null) { return false; } else { return true; } } /// <summary> /// Checks if user accoung is locked /// </summary> /// <param name="sUserName">The username to check</param> /// <returns>Retruns true of Account is locked</returns> public bool IsAccountLocked(string sUserName) { UserPrincipal oUserPrincipal = GetUser(sUserName); return oUserPrincipal.IsAccountLockedOut(); } #endregion #region Search Methods /// <summary> /// Gets a certain user on Active Directory /// </summary> /// <param name="sUserName">The username to get</param> /// <returns>Returns the UserPrincipal Object</returns> public UserPrincipal GetUser(string sUserName) { PrincipalContext oPrincipalContext = GetPrincipalContext(); UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, sUserName); return oUserPrincipal; } /// <summary> /// Gets a certain group on Active Directory /// </summary> /// <param name="sGroupName">The group to get</param> /// <returns>Returns the GroupPrincipal Object</returns> public GroupPrincipal GetGroup(string sGroupName) { PrincipalContext oPrincipalContext = GetPrincipalContext(); GroupPrincipal oGroupPrincipal = GroupPrincipal.FindByIdentity(oPrincipalContext, sGroupName); return oGroupPrincipal; } #endregion #region User Account Methods /// <summary> /// Sets the user password /// </summary> /// <param name="sUserName">The username to set</param> /// <param name="sNewPassword">The new password to use</param> /// <param name="sMessage">Any output messages</param> public void SetUserPassword(string sUserName, string sNewPassword, out string sMessage) { try { UserPrincipal oUserPrincipal = GetUser(sUserName); oUserPrincipal.SetPassword(sNewPassword); sMessage = ""; } catch (Exception ex) { sMessage = ex.Message; } } /// <summary> /// Enables a disabled user account /// </summary> /// <param name="sUserName">The username to enable</param> public void EnableUserAccount(string sUserName) { UserPrincipal oUserPrincipal = GetUser(sUserName); oUserPrincipal.Enabled = true; oUserPrincipal.Save(); } /// <summary> /// Force disbaling of a user account /// </summary> /// <param name="sUserName">The username to disable</param> public void DisableUserAccount(string sUserName) { UserPrincipal oUserPrincipal = GetUser(sUserName); oUserPrincipal.Enabled = false; oUserPrincipal.Save(); } /// <summary> /// Force expire password of a user /// </summary> /// <param name="sUserName">The username to expire the password</param> public void ExpireUserPassword(string sUserName) { UserPrincipal oUserPrincipal = GetUser(sUserName); oUserPrincipal.ExpirePasswordNow(); oUserPrincipal.Save(); } /// <summary> /// Unlocks a locked user account /// </summary> /// <param name="sUserName">The username to unlock</param> public void UnlockUserAccount(string sUserName) { UserPrincipal oUserPrincipal = GetUser(sUserName); oUserPrincipal.UnlockAccount(); oUserPrincipal.Save(); } /// <summary> /// Creates a new user on Active Directory /// </summary> /// <param name="sOU">The OU location you want to save your user</param> /// <param name="sUserName">The username of the new user</param> /// <param name="sPassword">The password of the new user</param> /// <param name="sGivenName">The given name of the new user</param> /// <param name="sSurname">The surname of the new user</param> /// <returns>returns the UserPrincipal object</returns> public UserPrincipal CreateNewUser(string sOU, string sUserName, string sPassword, string sGivenName, string sSurname) { if (!IsUserExisiting(sUserName)) { PrincipalContext oPrincipalContext = GetPrincipalContext(sOU); UserPrincipal oUserPrincipal = new UserPrincipal(oPrincipalContext, sUserName, sPassword, true /*Enabled or not*/); //User Log on Name oUserPrincipal.UserPrincipalName = sUserName; oUserPrincipal.GivenName = sGivenName; oUserPrincipal.Surname = sSurname; oUserPrincipal.Save(); return oUserPrincipal; } else { return GetUser(sUserName); } } /// <summary> /// Deletes a user in Active Directory /// </summary> /// <param name="sUserName">The username you want to delete</param> /// <returns>Returns true if successfully deleted</returns> public bool DeleteUser(string sUserName) { try { UserPrincipal oUserPrincipal = GetUser(sUserName); oUserPrincipal.Delete(); return true; } catch { return false; } } #endregion #region Group Methods /// <summary> /// Creates a new group in Active Directory /// </summary> /// <param name="sOU">The OU location you want to save your new Group</param> /// <param name="sGroupName">The name of the new group</param> /// <param name="sDescription">The description of the new group</param> /// <param name="oGroupScope">The scope of the new group</param> /// <param name="bSecurityGroup">True is you want this group to be a security group, false if you want this as a distribution group</param> /// <returns>Retruns the GroupPrincipal object</returns> public GroupPrincipal CreateNewGroup(string sOU, string sGroupName, string sDescription, GroupScope oGroupScope, bool bSecurityGroup) { PrincipalContext oPrincipalContext = GetPrincipalContext(sOU); GroupPrincipal oGroupPrincipal = new GroupPrincipal(oPrincipalContext, sGroupName); oGroupPrincipal.Description = sDescription; oGroupPrincipal.GroupScope = oGroupScope; oGroupPrincipal.IsSecurityGroup = bSecurityGroup; oGroupPrincipal.Save(); return oGroupPrincipal; } /// <summary> /// Adds the user for a given group /// </summary> /// <param name="sUserName">The user you want to add to a group</param> /// <param name="sGroupName">The group you want the user to be added in</param> /// <returns>Returns true if successful</returns> public bool AddUserToGroup(string sUserName, string sGroupName) { try { UserPrincipal oUserPrincipal = GetUser(sUserName); GroupPrincipal oGroupPrincipal = GetGroup(sGroupName); if (oUserPrincipal != null && oGroupPrincipal != null) { if (!IsUserGroupMember(sUserName, sGroupName)) { oGroupPrincipal.Members.Add(oUserPrincipal); oGroupPrincipal.Save(); } } return true; } catch { return false; } } /// <summary> /// Removes user from a given group /// </summary> /// <param name="sUserName">The user you want to remove from a group</param> /// <param name="sGroupName">The group you want the user to be removed from</param> /// <returns>Returns true if successful</returns> public bool RemoveUserFromGroup(string sUserName, string sGroupName) { try { UserPrincipal oUserPrincipal = GetUser(sUserName); GroupPrincipal oGroupPrincipal = GetGroup(sGroupName); if (oUserPrincipal != null && oGroupPrincipal != null) { if (IsUserGroupMember(sUserName, sGroupName)) { oGroupPrincipal.Members.Remove(oUserPrincipal); oGroupPrincipal.Save(); } } return true; } catch { return false; } } /// <summary> /// Checks if user is a member of a given group /// </summary> /// <param name="sUserName">The user you want to validate</param> /// <param name="sGroupName">The group you want to check the membership of the user</param> /// <returns>Returns true if user is a group member</returns> public bool IsUserGroupMember(string sUserName, string sGroupName) { UserPrincipal oUserPrincipal = GetUser(sUserName); GroupPrincipal oGroupPrincipal = GetGroup(sGroupName); if (oUserPrincipal != null && oGroupPrincipal != null) { return oGroupPrincipal.Members.Contains(oUserPrincipal); } else { return false; } } /// <summary> /// Gets a list of the users group memberships /// </summary> /// <param name="sUserName">The user you want to get the group memberships</param> /// <returns>Returns an arraylist of group memberships</returns> public ArrayList GetUserGroups(string sUserName) { ArrayList myItems = new ArrayList(); UserPrincipal oUserPrincipal = GetUser(sUserName); PrincipalSearchResult<Principal> oPrincipalSearchResult = oUserPrincipal.GetGroups(); foreach (Principal oResult in oPrincipalSearchResult) { myItems.Add(oResult.Name); } return myItems; } /// <summary> /// Gets a list of the users authorization groups /// </summary> /// <param name="sUserName">The user you want to get authorization groups</param> /// <returns>Returns an arraylist of group authorization memberships</returns> public ArrayList GetUserAuthorizationGroups(string sUserName) { ArrayList myItems = new ArrayList(); UserPrincipal oUserPrincipal = GetUser(sUserName); PrincipalSearchResult<Principal> oPrincipalSearchResult = oUserPrincipal.GetAuthorizationGroups(); foreach (Principal oResult in oPrincipalSearchResult) { myItems.Add(oResult.Name); } return myItems; } #endregion #region Helper Methods /// <summary> /// Gets the base principal context /// </summary> /// <returns>Retruns the PrincipalContext object</returns> public PrincipalContext GetPrincipalContext() { PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sDefaultOU, ContextOptions.SimpleBind, sServiceUser, sServicePassword); return oPrincipalContext; } /// <summary> /// Gets the principal context on specified OU /// </summary> /// <param name="sOU">The OU you want your Principal Context to run on</param> /// <returns>Retruns the PrincipalContext object</returns> public PrincipalContext GetPrincipalContext(string sOU) { PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sOU, ContextOptions.SimpleBind, sServiceUser, sServicePassword); return oPrincipalContext; } #endregion }
Now this is how to use it.
ADMethodsAccountManagement ADMethods = new ADMethodsAccountManagement(); UserPrincipal myUser = ADMethods.GetUser("Test"); myUser.GivenName = "Given Name"; myUser.Surname = "Surname"; myUser.MiddleName = "Middle Name"; myUser.EmailAddress = "Email Address"; myUser.EmployeeId = "Employee ID"; myUser.Save();
Great info!
One question, could you show a nice example of editing an existing user?
If you have noticed there is no more attribute editing function on the library I created as it is now exposed on the UserPrincipal namespace itself so if you want to update information such as name, last name, employee id as some samples you can do it by searching for the user like this
ADMethodsAccountManagement ADMethods = new ADMethodsAccountManagement();
UserPrincipal myUser = ADMethods.GetUser("your Username");
and assigning values to it like such:
myUser.GivenName = "Given Name";
myUser.Surname = "Surname";
myUser.MiddleName = "Middle Name";
myUser.EmailAddress = "Email Address";
myUser.EmployeeId = "Employee ID";
myUser.Save();
using this code i am able to create new user but with blank password, code is creating user with blank password.
Also i need to create user with Admin privilages (should be memebr of Administrator).
Please reply…….
Do you have an example of using any of the other methods like removing user from a group, adding user to a group.
You can use this two methods RemoveUserFromGroup and AddUserToGroup, the parameters are only User Name and Group Name, if it doesnt find any it returns a boolean variable.
Pingback: Active Directory Objects and C# « Raymund Macaalay's Dev Blog
I am trying to hook up with Active directory to get the Group of the user using System.DirectoryServices.AccountManagement.
When I am running the Application from VS2010 it Authenticate user and Display the Group as well.
But when I am browsing application from IIS 5.1 it showing error while checking the group.
“System.DirectoryServices.DirectoryServicesCOMException: Logon failure: unknown user name or bad password.”
PrincipalContext pc = new PrincipalContext(ContextType.Domain, “TEST1”)
On Sentence
UserPrincipal.FindByIdentity(pc, userName);
Kindly provide some help.
Can you give me your codes on GetPrincipalContect part so I can debug it properly.
hi,
Please find the code of GetPrincipalContect as given below.
public PrincipalContext GetPrincipalContext()
{
//PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sDefaultOU, ContextOptions.SimpleBind, sServiceUser, sServicePassword);
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, “TEST1”);
return oPrincipalContext;
}
Looks like you are using PrincipalContext(ContextType, String) where the or your “TEST1” will be the name of the domain or server hosting the ApplicationDirectory instance. Which means the application will set the default username and password when the instance of the Principal Cotnext initializes, this will be fine on your machine as it will inherit your user who is logged in to the machine but when using IIS if you are not using Integrated Windows Authentication with the Anonymous Access off then it would use the IUSR_SERVERNAME account to initiallize the Principal Cotnext, but if you are using the the Integrated Windows Authentication with the Anonymous Access off can you do a Response.Write of the username the site is running as.
Hi,
I tried to get the username by WindowsIdentity.GetCurrent().Name.ToString()
When I am browsing application from IIS ( Integrated Windows Authentication with the Anonymous Access off )
and try to get the user name it showing “PC_NAMEASPNET”
and
When I am running from VS2010 it showing “DOMAINMyUserId”
who is logged in to the machine.
Hi this has been resolved.
When code runs localy using VS2010 it run under my conditionals (user Logon on PC)
And when it runs from IIS it runs under a small right account.
So I tried impersonate tag in Web.Config with username and password
And it worked proper.
Thanks You very Mush rsmacaalay for your suggession.
Good to know its working now
Pingback: How to use AD Attributes not represented in UserPrincipal, GroupPrincipal and ComputerPrincipal « Raymund Macaalay's Dev Blog
Could you please demonstrate a more complete use of the RemoveUserFromGroup function?
Thank you.
Its simple to use all you need is an AD UserName and AD GroupName so for example you have a username “raymund” and group name “administrators” then the usage is RemoveUserFromGroup(“raymund”, “administrators”), hope this clarifies your question.
Great stuff! I think the logic on some of the group methods is backwards though. For example, I would think IsUserGroupMember should be like this:
if (oUserPrincipal == null || oGroupPrincipal == null)
{
return false;
}
else
{
return oGroupPrincipal.Members.Contains(oUserPrincipal);
}
so that if either the user or the group is not found, the method returns false.
Thanks for pointing that out, I noticed that as well in my codes before but forgot to change my blog post.
Updating it now so all with || are now using != and && i.e
Hi.
I’m trying to use your code, but
At: AddUserToGroup, at line: oGroupPrincipal.Members.Add(oUserPrincipal);
I Keep getting this exception: System.DirectoryServices.AccountManagement.PrincipalOperationException : Information about the domain could not be retrieved (1355).
Do you have a solution?
That error means that the “The specified domain either does not exist or could not be contacted.” So the best thing to do first is add the IP address of domain controller that you are using on the DNS server list on the machine the code is running on and make sure thats the first on the list, after doing that do an
ipconfig /flushdns
Here is where you add it

THanks, Problem solved. But is there another alternative?
I don’t know if in production environment I’ll be able to do this.
Ops! Not solved, I thought it was, but forgot to change the code to the original one =/
I ‘Solved’ this using old DirectoryEntry, but I wish to use AccManagement namespace =/
This is a known issue with .NET 3.5 when working with groups. I had the same problem when accessing a test Active Directory in a different domain.
http://elegantcode.com/2009/03/21/one-scenario-where-the-systemdirectoryservices-accountmanagement-api-falls-down/
Too bad =/
Okay then, I’ll go back to directory entries =/
Actually, you should probably look at using the overload if you are connecting that takes the PrincipalContext. This helps the GetGroups even without the DNS server being the first in the list, or even if the computer doesn’t belong to the same Active Directory.
Could you show an example of how to update for example the department field and office field using this?
Sorry for the late reply but here it is, I have a separate post regarding that one which you can find here http://anyrest.wordpress.com/2010/10/14/how-to-use-ad-attributes-not-represented-in-userprincipal-groupprincipal-and-computerprincipal/
Hi. It’s very useful class but I can’t use this , because I showing error Logon failure: unknown user name or bad password. I want add user to AD in Windows 2003 server. I saw that Kishor resolved this problem but i can’t understend how he did this. Please help me 🙁
P.S. Sorry for my english.This is not very well, but i try learn this 🙂
Can you let me know how your environment work first? Where is your code running? Whats calling it? etc. Then I guess we can start from there.
OK , I try use for create new user in domain
UserPrincipal myNewUser = ADMethods.CreateNewUser("test.com", tbLogin.Text.Trim(), tbPassword.Text.Trim(),
"Name", "Simple name", "Simple surname", "893456463", "dfsg@sibmail.com");
myNewUser.Save();
and i showing message “the user name or password unidentified” .I lunch application on the server machine
tbLogin is textbox.text = “login”;
tbPassword is textbox.tex = “password”;
“test.com” is name of domain
private string sDomain = “test.com”;
private string sDefaultOU = “OU=Users,OU=Test,DC=test,DC=com”;
private string sDefaultRootOU = “DC=test,DC=com”;
private string sServiceUser = @”Администратор”;
private string sServicePassword = “12345”;
Can you also give me your code for the GetPrincipalContext
I have a user in one domain – say domain A. This user is a member of a few groups in Domain A and a few groups in Domain B. The GetUserGroups function will only return the groups in Domain A. How can I get the groups for Domain B as well? Any help is greatly appreciated.
You need to connect in two different PrincipalContexts which you can programatically assign in the PrincipalContext method. This means you execute User.GetGroups(PrincipalContext) in two different PrincipalContexts and merge the results.
Pingback: Synchronizing Google Groups and Active Directory Group Members « Raymund Macaalay's Dev Blog
Nice and thank you very much!!. I’ve failed to see the use of the variable : sDefaultRootOU
Hi,
Firstly thank to teach us here. Really appreaciate what you have done. Yup, your blog is one of must see for me :).
I cannot help myself keep wondering on this article about 3 things:
1. My domain have deep OU level – more than 3. Let say, I have OU “Deparments” right under root, then OU “” and OU “”. Such it become contoso.edu->Departments->ComputerScience->2011. Can the GetPrincipalContext() be able to validate user just only by given root OU?
2. My domain also have other 5 sub domains, with all the domains are GCs. Can I do search/validate user just by giving the root domain with UserName complete with domain, such validate “khairil@student.contoso.edu from root domain “contoso.edu”?
3. I have Forest level trust relation with other forest, fictionally named “fabrikam.com”. Can I validate their user using your code? What are modification that I need to do?
Sorry, asking you to many questions, I just new comer to AD. Anyway, thank you very much for your articles.
-khairil-
Hi kharil,
1. sDefaultOU and anything below it would be the scope of any queries or actions you do in Active Directory. So the answer on your question is yes, regardless how deep your OU is as long as it belong to the root then it will be fine. But please note that sDefaultRootOU was not used in the above code, it was my mistake.
2. You have to change sub domains by changing sDomain and sDefaultOU. And sub domains will be treated as a different repository thats why in Windows Login you are asked the option of which domain to log in to as it will not search your user credentials in other sub domains.
3. Like in item 2 you need to be specific to a domain.
I hope i understood your questions and answered them 🙂
Hi Raymund,
Thanks for the tips, 🙂 yup that answered my questions.
At first I thought, when a domain is GC I do not have to specify a domian, just giving UserName with full user@domain combination. You have clear it up for me.
Just another question, do “sServiceUser” need to be a special account like domain admin or enterprise admin,or just any normal account will do?
Thank you very much for the answer. Happy weekend then.
-Khairil-
Hi Raymund,
I think I’ve found the answer for my forth question. Normal user account will do.
-Khairil-
Greetings,
Have you noticed any problems with caching? I have a project where I used these AccountManagement principals and I can’t seem to figure out how to refresh the cache. Removing items from a group is particularly visible. It takes a variable amount of time before removed items are gone which I would presume is the normal interval that the cache is flushed. groupPrincipal,Save() does not flush the local cache apparently.
Your thoughts are appreciated.
Do you have multiple Domain Controllers? If you have, that might be the case as it need to synchronize between different controllers and te time depends on the amount of data being synchronized between the two. To actually confrim this you need to view items directly on the Domain Controller your application is connected to via the Active Directory Users and computers
Hi, I am new to active directory , I have a task where i will be having user names and i nedd to fing corresponding group and ou related and second I need to move user from one group to another. How can I achive this I tried all near possibalities given in posts on internet.Hope you will reply soon for my query.
Thanks
Panindra Nadig
What do you mean by “i nedd to fing corresponding group and ou related”? also OU you can move but groups you can join an unjoin those are two different things. So for the groups you can use the AddUserToGroup and RemoveIuserFromGroup methods
Hey thanks for the code, looks like its working pretty great in VS2010 with running credentials but I cant get it work running under supplied credentials on the IIS server by enabling anonymous mode. I am fairly new to this but how could i run everything under the credentials in IIS and not a plain text file.
Not a good idea to run it in anonymous mode, you either need to run it with IIS Credentials that have very defined security roles or you can do Windows authentication and let the users credentials define what methods he have access to run.
How would I get a list of users and their managers using your code?
Managed to create the method in the meantime
public struct ADUser
{
public String Name;
public String Surname;
public String AccountName;
public String PrincipleName;
}
public ArrayList GetUserList()
{
PrincipalContext oPrincipalContext = GetPrincipalContext(sDefaultOU);
ArrayList Results = new ArrayList();
using (var searcher = new PrincipalSearcher(new UserPrincipal(oPrincipalContext)))
{
foreach (var result in searcher.FindAll())
{
ADUser LoadUser;
DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
LoadUser.Name = de.Properties[“givenName”].Value.ToString();
LoadUser.Surname = de.Properties[“givenName”].Value.ToString();
LoadUser.AccountName = de.Properties[“givenName”].Value.ToString();
LoadUser.PrincipleName = de.Properties[“givenName”].Value.ToString();
Results.Add(LoadUser);
}
}
return Results;
}
You obviously need to replace the properties with your own.
http://www.kouti.com/tables/userattributes.htm
Sorry for the late reply was in TechEd last week anyways better late than never.
For your question, Here is a sample on how you get a list of users returning as
an ArrayList
and to get the users manager here is the method
when i am validating username and password by
PrincipalContext oPrincipalContext = GetPrincipalContext();
return oPrincipalContext.ValidateCredentials(sUserName, sPassword);
this function it gives always return false but username and password is correct
using System;
using System.DirectoryServices;
public class RenameObject
{
public static void Main()
{
DirectoryEntry de = new DirectoryEntry(
“LDAP://192.168.1.100/ou=auditing, ou=accounting, dc=ispnet1, dc=net”,
“cn=Administrator, dc=ispnet1, dc=net”, “password”,
AuthenticationTypes.ServerBind);
DirectoryEntries des = de.Children;
DirectoryEntry badObject = des.Find(“cn=test”);
badObject.Rename(“cn=testing”);
de.CommitChanges();
de.Close();
}
}
Hello, ¿can i rename group of users with GroupPrincipal?
GroupPrincipal gp=GetGroup(“TEST”);
gp.name=”NEW NAME”;
gp.save(); //ERROR not possible change RDN !
Any ideas? Very thank you
RDN or Relative Distinguished Name is like a primary key on the database so you cant rename that, what you can do is change the display name but if you really want to change the name you need to drop and recreate it programatically, I guess thats what happens when you use the Active Directory Users and Computers, it just looks like you are renaming it.
using System;
using System.DirectoryServices;
public class RenameObject
{
public static void Main()
{
DirectoryEntry de = new DirectoryEntry(
“LDAP://192.168.1.100/ou=auditing, ou=accounting, dc=ispnet1, dc=net”,
“cn=Administrator, dc=ispnet1, dc=net”, “password”,
AuthenticationTypes.ServerBind);
DirectoryEntries des = de.Children;
DirectoryEntry badObject = des.Find(“cn=test”);
badObject.Rename(“cn=testing”);
de.CommitChanges();
de.Close();
}
}
Thank you, I have recently been looking for details about this subject matter for ages and yours is the best I have found so far.
I am hoping I can get some help here. How can I copy an AD user in order to create another AD user? For example, I have a template user that I simply want to copy and create a new user JSmith. JSmith is now EXACTLY like the template user except of course for uniquely needed fields such as username and such. Is this possible? Please assist.
@Peter: I would set a specific user ( so create a user or use an existing one) as the template and create a function to fetch all of the details of that user, leaving out certain details like the email address, name, surname etc that would be unique for the new user to be created. Then use the functionality to create a new user using those details. If this is a constant function that you would be using, I would suggest that you generate an xml file with the details and just read the file instead of hammering the AD
But would this copy everything from the original user? All groups and rights and settings, etc.?
And file permissions?
Hi Peter, while its not a good practice to copy ones credentials it will be possible but like what Thomas said you need to create a template and thats the best practice. That template can be on XML or in SQL where it defines a specific definition for the user that you will be creating.
Also on your question regarding the file and folder permissions well if the file or folder was granted permission because of an AD group then it would be easy but if its granted by the username then good luck as you dont have any reference from AD what files have been granted unless you iterate to all of the files and folders and check the permissions. Hope this helps.
I am a very long time watcher and I just thought I’d drop by and say hello there for your 1st time. I actually delight in your posts. Thanks
This is great and very helpful with the application I have been creating. Right now I need the ability to create and delete computers in Active Directory. I have been able to do it using the more combersome method, but I like the cleaniness of this method you have display so well. Would you happen to have example of both methods?
One thing that I found while attempting to create the computer that it wasn’t getting placed into the correct account type and had to set the userAccountControl to 4128 in order for it to get enabled and set up so it could attached to the domain…also had to set the PrimaryGroupID to 515…need something clean
Oh and another Active Directory task that I like to be able to do in my application is the ability to rename a user to change the following properties: Full Name (cn), First Name (givenName), Last Name (sn), Display Name (displayName) and the User logon – we have a special formatting rule for the user logon id so I would have to create a new logon based on that rule and then set the userPrincipalName and SAMAccountName with the new value.
Pingback: how do i create new OU in Active Directory using DirectoryServices.AccountManagement in .net 3.5 or 4 | trouble86.com
i’d like to add to your class a method that creates a new OU (if the OU doesnt exist already) using principals and not using the old System.DirectoryServices
any idea how to do that ?
i’ve also posted it here:
http://stackoverflow.com/questions/7792646/how-do-i-create-new-ou-in-active-directory-using-directoryservices-accountmanage/7793101#7793101
thanks!
The answer given in StackOver Flow is correct there is no way in .Net 3.5 you can manage Organizational Units so you have to use the DirectoryEntry Object in the System.DirectoryServices.ActiveDirectory namespace so here is a mehod just to achieve what you want
public void CreateNewOU(string sOU, string sNewOU, string sOUDescription)
{
string sLDAPPath = "LDAP://" + sDomain + "/" + sOU;
DirectoryEntry oParentOU = new DirectoryEntry(sLDAPPath);
DirectorySearcher oDirectorySearcher = new DirectorySearcher(oParentOU);
oDirectorySearcher.Filter = "(" + sNewOU + ")";
oDirectorySearcher.SearchScope = SearchScope.Subtree;
SearchResult oSearchResult = oDirectorySearcher.FindOne();
if (oSearchResult == null)
{
DirectoryEntry oNewOU = oParentOU.Children.Add(sNewOU, "OrganizationalUnit");
oNewOU.Properties["description"].Add(sOUDescription);
oNewOU.CommitChanges();
}
}
usage
ADMethodsAccountManagement myAD = new ADMethodsAccountManagement();
myAD.CreateNewOU("OU=Parent OU,DC=com,DC=test", "OU=New OU", "Test Organizational Unit Description");
I am using the GetUser method as described above. When I execute the FindByIdentity method, I get an exception with “A referral was returned from the server”. I’m a newbie in terms of AD, so I’m not sure what this means.
I’m using the following connection string. This was the only way I could get past “Unable to connect to server” and “Invalid Login/Password” messages.
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, “MyDomain.local”, “dc=domain,dc=com”, ContextOptions.SimpleBind, “MyDomain\” + sServiceUser, sServicePassword);
Can you give me your full codes where form your connection to the method you are using, as well as your full exception so that I can debug it.
I think I have it figured out. When I specify MyDomain.local as the domain name, I then need to specify “dc=MyDomain,dc=local”. Before I had “com” instead of “local”.
Thanks for the response, though.
Hi,
Good information ,
Can you please show a code to get all members of a group?
thank you in advance
Fred
Usng the GetGroup Method above then the code below
Usage
Excellent !!! Thank you
Hi,
Ok , the range of members groups seems to be 0-1500 …
how I can get or to know the count of members when it more than 1500+
thank u in advance
Fred
Your AD Policy might restrict you to output only 1500 objects at a time to change that limit you have to change you policy, here is my post to do it. http://anyrest.wordpress.com/?s=Increase+1000+Records+Maximum+Page+Size+of+Active+Directory
Hi again
Could you please show a code to get all users under criteria ?
e.g : I would like to search all users where
(&(employeeType=employee)(extensionAttribute=*-US))
thank you in advance
Fred
Since those attributes are not represented in the UserPrincipal object you need to extend it and here is my article regarding that topic http://anyrest.wordpress.com/2010/10/14/how-to-use-ad-attributes-not-represented-in-userprincipal-groupprincipal-and-computerprincipal/. Once you had extended the attributes to have employeeType and extensionAttribute you can now use the usual PrincipalSearcher like such with the combination of the library above.
Hi,
Thank you for guidance , I will be checking it out
Fred
Hi Fred, did u solve this extensionAttribute issue ?
I am trying to provide a role-based access to my intranet system using AD and different web-apps are listed as extensioAttributes.
so I need to check if Use has perticular app in his/her list or not ? if yes then its OK otherwise they should be redirected to mycompanyhome.company.co.uk
please post your solution idea.
Raymund, can you please explain this with some more example
regards
Maulin
Nice content, but you shouldn’t write code like this:
if (oUserPrincipal.AccountExpirationDate != null)
{
return false;
}
else
{
return true;
}
It’s sufficient, and at least equally as clear, to write:
return oUserPrincipal.AccountExpirationDate == null;
This is very good & thanks.
Do you have an example of retrieving all Distribution Groups (Exchange Distribution Lists) from Active Directory?
Thank you.
Sorry, I need the email address associated with all found Distribution Groups.
Please read my reply to Fred Roines http://anyrest.wordpress.com/2010/06/28/active-directory-c/#comment-541, I gave him a method for this one. It should work on all Security and Distribution type groups
Thank you for replying.
I am not looking to retrieve the members of a group. I need to retreive all email Dustribution Groups (Exchange Dustributions Lists) and their associated email address. I seems that the answer in the link above referes to members of a group.
Your help is appreciated.
And to use it
please note you have to use some of the existing methods above for this to work, also add this one below
Hi,
as mentioned this is working just fne and thanks for your help. Just one furhter point, I have a requirement to return Dynmanic Distribution Groups which are available in Exchange 2007+ environments. Is it possible to retrieve Dynamic Distribution Groups using System.DirectoryServices.AccountManagement or do I need another method? If you could provide
an example that would be great.
Thank you.
Any chance to search after attribute “department” for specified user?
Hi great! Thanks all works fine!
Hi ,
Question : when using System.DirectoryServices namespace , you can use .addrange to add multiple members to a group in a single operation, so is it possible by using System.DirectoryServices.AccountManagement
if yes, could you please show an example? =)
Thank in advance
Fred
hi ,
i want to set a permission in active directory and user controls at particular OU and all sub OU’S under this OU to authenticated user’s for read permission.i am using console application in c#.please tell me how to implement it using ldap in c#
That’s are great article, I got some good knowledge. But one thing i need to know (sorry have no idea). what is the real / practical usage of this code. Could you please suggest any example where this trick is helpful.
If youre developing some sort of Identity Mangement Solution or even just a user management then this would be a great use.
Great post.
Is it possible to get the password of the user.why becoz i am creating reset password webpart in sharepoint fba site.the users can change their passwords.(both fba and ad users).
No its not possible, I have the same situation before “creating a password reset as a SP web part” what Ive done is extended AD the schema to have the secret question id and secret question answer (encrypted of course). And to force users to fill this up is when the fire up sharepoint front page I have a web part that intercepts the landing page and checks if they have already set up the secret question if not they will be redirected to a setup page otherwise they continue normally
Excellent piece of work!
Congratulations for it and a million thanks for saving me of such a big effort!
I am unable to find manager object based on its name property if the user and its manager are in different domain. Lets say top domain is BIG and under that we have subdomain1,2,3 etc. User belong to subdomain1 and manager in subdomain2. Search operation not working on TOP domain.
Below is my code
UserPrincipal oUserPrincipal = GetUser();
PrincipalContext oPrincipalContext = GetPrincipalContext();
UserPrincipalEx ex = UserPrincipalEx.FindByIdentity(oPrincipalContext, oUserPrincipal.SamAccountName);
if (sFieldName == ”manager”)
{
string strManager = ex.GetUserFieldData(sFieldName);
if (!string.IsNullOrEmpty(strManager))
{
UserPrincipal oManagerPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, strManager);
return oManagerPrincipal.DisplayName + ”$$$” + oManagerPrincipal.EmailAddress;
}
return ””;
}
return ex.GetUserFieldData(sFieldName);
At line UserPrincipal oManagerPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, strManager); oPrincipalContext belong to user who belong to subdomain1 and strmanager is the name of manager which I get from extendedUserPrincipal.
Plz suggest
WordPress.com / Gravatar.com credentials can be used.
This is an excellent article. Its helping me to design an application that will sync users from a DB to AD. Now i am just stuck at a problem, how do i only search for users in the entire AD. if dont know the names of the nodes. I saw in AD that there is a Type that says “USER” but i cant find this in the objects that i have from your code.
Please help!
The user principal handles it so no need to search by “user” unlike the old .net 2.0 way.
I am getting errors on
ADMethodsAccountManagement — Type or namespace could not be found
and
ActiveDirectory — The name ‘ActiveDirectory’ could not be found.
Here are my namespaces:
using System;
using System.Collections;
using System.Text;
using System.Windows.Forms;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Data;
using System.Configuration;
Add it as a reference on your project
Great blog. very helpful, thank you very much.
My question is indirectly associated with AD. Can you show some code for reads data from the syslog about AD changes and leading them to the same AccountManagment classes ? If you made this code for read/erite AD objects you most likely made and the code for changes monitoring.
Thank You.
Hi,
Thanks for providing such a simple and useful methods for handling AD. Everything is working fine except SetUserPassword Method which is not taking into account the Password History Policy of Ad. It is just resetting it to the value we provide. Unlike SetUserPassword, ChangePassword is taking care of all the AD policies. But I can’t use ChangePassword method when user is not having his old password. So in that case I have to use SetUserPassword method.
Please help to resolve this issue.
Thanks!
That is really how it works as SetUserPassword is meant for Admins similar to reset password in Active Directory Users and Computers while ChangeUserPassword is meant for end users to reset their password meaning they should know their old one
Ok, but I am still wondering how the paid application like NetWrix Password Manager and AD SelfService Plus have implemented Reset Password Functionality. We have downloaded the trial version of NetWrix and tried to Reset the password by just providing the new password. It changes the password with all AD password policies taking into account including the history policy.
Its been almost 2 month I am searching for the solution. Please suggest some solution, I’ll be very grateful to you.
Thanks for the great post. Helped me a lot. Appreviate your time and effort.
Have a question. Is there an easy way to find out all the groups and distribution list and not the users from a group.
ie. X group has 5 members of which 3 are users and 2 are distribution list/groups. How to get only the 2 sub groups from the group X?
I tried the following but that is not helping..
from principal in orgGroupPrincipal.Members
where principal is GroupPrincipal
select principal as GroupPrincipal;
Any suggestion?
Thanks for your time.
Got it…I used the property StructuralObjectClass == “group” to distinguish the user from class. 🙂
Is there an alternate or better way; just curious..
First thanks so much for your work on this. I have been using it for over a year without problems.
That is until today. The WebApp I wrote last month was working on my Laptop and the Server, but today I noticed it is no longer working on the server. I have reboot, redeployed the entire webapp and still nothing fixed it.
I am hoping you might have seen this once or twice in your work with this…
Error:
System.NullReferenceException: Object reference not set to an instance of an object.
Line:
PrincipalSearchResult oPrincipalSearchResult = oUserPrincipal.GetGroups();
Full method below.
///
/// Gets a list of the users group memberships
///
/// The user you want to get the group memberships
/// Returns an arraylist of group memberships
public ArrayList GetUserGroups(string sUserName)
{
ArrayList myItems = new ArrayList();
UserPrincipal oUserPrincipal = GetUser(sUserName);
PrincipalSearchResult oPrincipalSearchResult = oUserPrincipal.GetGroups();
foreach (Principal oResult in oPrincipalSearchResult)
{
myItems.Add(oResult.Name.ToLower());
}
return myItems;
}
I will keep looking and post if I fix it. I hope you can help.
I think its either the User you are searching does not have groups, the user is not existing anymore or permissions have changed
Thanks for the fast response. As it is working for me on my laptop, just not the server as me. So I exist, and I have groups. I am passing in the current users.
UserID = WindowsIdentity.GetCurrent().Name.Substring(WindowsIdentity.GetCurrent().Name.LastIndexOf(@””) + 1);
I just strip of the domain part. Just odd that the UserGroups is the only thing not working.
Great News, I have fixed the problem. After creating a new site and pushing the code out only to find it works fine on the new site, I went back to the production site and found someone had turned on “Enable Anonymous Access”. Once I turned that off all the code started working correctly.
Pingback: Active Directory средствами C# • Алексей Петрачук
Pingback: Getting a User Or AllUsers from Active Directory using C# « Kazim's space
Thx for your valuable efforts…
How can i search user by employee ID number
hi,
I need to rename the user id with new one. can you give me a sample code
The account management helper class works great. Do you happen to have some code that would add missing items from the UserPrincipal… something like this below.
The idea would be to add all of the missing items so that they could be set in code.
It would be helpful to see not only how they get set, but how they would then get used in code..
Thanks in advance.
Scott
Here is some sample code….
[DirectoryProperty(“initials”)]
public string initials
{
get
{
object[] result = this.ExtensionGet(“initials”);
if (result != null)
{
return (string)result[0];
}
else
{
return null;
}
}
set { this.ExtensionSet(“initials”, value); }
}
Have a look at this post http://anyrest.wordpress.com/2010/10/14/how-to-use-ad-attributes-not-represented-in-userprincipal-groupprincipal-and-computerprincipal/
Thx for your great effort.
i receive error while use : logon failure unknown user name or bad password
private string sDomain = “test.com”;
private string sDefaultOU = “OU=testUsers,DC=testCORP,DC=test,DC=com”;
private string sDefaultRootOU = “DC=testCORP,DC=test,DC=com”;
private string sServiceUser = @”admintest”;
private string sServicePassword = “test.123”;
==============
private void btnuser_Click(object sender, EventArgs e)
{
try
{
ADMethodsAccountManagement userinfo = new ADMethodsAccountManagement();
UserPrincipal aduser = userinfo.GetUser(txtusername.Text);
Labtrueorfalse.Text = aduser.EmailAddress;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Good morning. I have a question ? How I can connect with Azure AD ?
An Excellent code, I am new to the .Net and I am trying to update the “ManagedBy” and “GrantSendOnBehalfTo” for a group, how can I use your Code to display and update the list of users in the mentioned group’s fields?
No as this is for managing users, you can do it though by using GroupPrincipal instead of UserPrincipal, then extend the class to get the other attributes not exposed. To do that follow this guide http://anyrest.wordpress.com/2010/10/14/how-to-use-ad-attributes-not-represented-in-userprincipal-groupprincipal-and-computerprincipal/
Pingback: How to use AD Attributes not represented in UserPrincipal, GroupPrincipal and ComputerPrincipal | SAMİ GÖNCÜ
HI ,
How to add user from domain XYZ into domain ABC distribution list.
example : XYZuserid1 , I want to add this user into domain ABC distribution list.
i.e. add non ABC user into ABC distribution list.
Please help.
Thanks,
Pranay
When using this if a username has a dash “-” in it I always receive not found. even through the user can be found in AD separately. So How do I get the dash “-” to be accepted.
Hi Raymund,
I am having difficulties trying to retrieve groups that a user is a member of using and I’m getting a NullReferenceException at this line..
Return oGroupPrincipal.Members.Contains(oUserPrincipal)
Am I trying to see if the user is a member of the ‘Staff’ group. I have verified that the user is valid already using ValidateCredentials but cannot seem to get the application to determine whether the user is a member of the group (which they are).
Here’s my code…
if (IsUserGroupMember(txtUsername.Text, “Staff”)) {
MessageBox.Show(“User is a member of the Staff group.”);
} else {
MessageBox.Show(“User not a member of the Staff group.”);
}
Here’s a link to the image showing more detail about the exeption: http://s17.postimg.org/pdjwqfm3z/Null_Exception.jpg
I am also having a problem trying to retrieve a list of groups that the user is a member of and get a NullReferenceException at this line too when I try using GetUserGroups:
PrincipalSearchResult oPrincipalSearchResult = oUserPrincipal.GetGroups();
Any help is much appreciated!
Thank you,
Paul
I think either the oUserPrincipal or oGroupPrincipal is null. You need to change it to If oUserPrincipal Is Nothing And oGroupPrincipal Is Nothing then ….
I’m trying to do an account unlock function using this. How would i first test the account is locked using IsAccountLocked and then perform UnlockUserAccount if the Account is locked.
Thanks
Thank you very much for this blog it’s very helpful.
I have one question: Is there any way to identify that a particular user is loggedin in any of the windows domain clients.
I am afraid you cant do that in the System.DirectoryServices.AccountManagement namespace
Hi Raymund,
I was just going through your post and it is very much relevant for what i am trying to do right now,
My requirement is to insert the data in specific OU by checking in csv file,
My OUs like below
India
Pune
Mumbai
Delhi
Germany
Contract
Full-time
above is the structure of my OU
Now about my csv
first name lastname jobtitle department manager location
now the requirement is to put that data into the Pune location OU if location in csv is Pune
can you please help me with
I think the test for IsUserExpired may not be correct. I’m working with a directory that has this nulled – and the user is not expired. Instead I changed it to this and I think this is correct:
if (oUserPrincipal.AccountExpirationDate != null)
{
if (oUserPrincipal.AccountExpirationDate > DateTime.Now)
return true;
return false;
}
else
{
return false;
}
hi.your code works great. do you have a sample code that will get the Audit aAcount logon events. I need to create a C# program to monitor the login/Logout of users in the Domain. please help.
Hi you can use the code above by querying the lastLogon and lastLogoff attribute of a certain user but if you have multiple domain controller you will have to query all of them separately and consolidate them before outputting your results
hi..but i need to monitor all users logon and logoff in the domain.i mean getting the list of user and their respective logon datetime and logof datetime .if you have sample code to share, im very much appreciate it. thank you
Like I said you can by listing all users and showing all lastLogon and lastLogoff attributes. By the code above and a little bit of thinking you can get what you need. But take note AD has a limitation of showing only 1000 records at a time. This is another issue but still can be resolved
hi raymund… i was not able to get the lastlogoff othe user. do you have a sample code for getting it.
You can refer to this post http://www.macaalay.com/2010/10/14/how-to-use-ad-attributes-not-represented-in-userprincipal-groupprincipal-and-computerprincipal/ and just find the lastLogon and lastLogoff attributes
hi i am having problem when entering correct username but bad password. GetUser method fails to execute becouse the username and password in not correct. Even if the account is locked, this GetUser method fails. Becouse of this i cant get the status of user (i.e is Accountlocked). could you please help me on this
Thanks
Thanks for this. Really sped things up for me today in a crash course in accessing users from code for an AD LDS setup.
I guess alot of this info is already here:
https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement(v=vs.110).aspx
But the information here is just way more…readable, especially when one is just googling and not quite sure what they are looking for. I wonder…who is charge of Microsoft Documentation Format!
Whenever I try to call IsUserGroupMember I get the following error:
Error System.Security.Authentication.AuthenticationException: The user name or password is incorrect.
—> System.DirectoryServices.DirectoryServicesCOMException: The user name or password is incorrect.
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_SchemaEntry()
at System.DirectoryServices.AccountManagement.ADStoreCtx.IsContainer(DirectoryEntry de)
at System.DirectoryServices.AccountManagement.ADStoreCtx..ctor(DirectoryEntry ctxBase, Boolean ownCtxBase, String username, String password, ContextOptions options)
at System.DirectoryServices.AccountManagement.PrincipalContext.CreateContextFromDirectoryEntry(DirectoryEntry entry)
at System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInit()
— End of inner exception stack trace —
at System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInit()
at System.DirectoryServices.AccountManagement.PrincipalContext.DoDomainInit()
at System.DirectoryServices.AccountManagement.PrincipalContext.Initialize()
at System.DirectoryServices.AccountManagement.PrincipalContext.get_QueryCtx()
at System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithTypeHelper(PrincipalContext context, Type principalType, Nullable`1 identityType, String identityValue, DateTime refDate)
at System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithType(PrincipalContext context, Type principalType, String identityValue)
at System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext context, String identityValue)
at CMManagement.GetUser(String sUserName) in Management.cs:line 91
at CMManagement.IsUserGroupMember(String sUserName, String sGroupName) in Management.cs:line 324
at CM12AutomationTest.Default.ExecuteCode_Click(Object sender, EventArgs e) in Default.aspx.cs:line 212
The function is called:
try
{
CMManagement cm = new CMManagement();
ResultBox.Text = cm.IsUserGroupMember(uName, gName).ToString();
}
catch (Exception eX)
{
ResultBox.Text = “Error ” + eX;
}
What am I missing?