I'm working on a project where I have to fetch the users from a particular OU in Active Directory.
I use the Dropdown menu to store all the OUs present. As soon as the user selects a particular OU and clicks on the button the users available for that should be displayed in the textbox.
This is the code being used:
public MainWindow()
{
InitializeComponent();
DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE");
string defaultContext = rootDSE.Properties["defaultNamingContext"][0].ToString();
DirectoryEntry domainRoot = new DirectoryEntry("LDAP://" + defaultContext);
DirectorySearcher ouSearcher = new DirectorySearcher(domainRoot);
ouSearcher.SearchScope = SearchScope.Subtree;
ouSearcher.PropertiesToLoad.Add("ou");
ouSearcher.PropertiesToLoad.Add("cn");
ouSearcher.SearchScope = SearchScope.Subtree;
ouSearcher.Filter = "(objectCategory=organizationalUnit)";
try
{
comboBox1.SelectedIndex = 0;
comboBox1.Items.Insert(0, "Select An OU");
string ouName;
foreach (SearchResult deResult in ouSearcher.FindAll())
{
ArrayList alObjects = new ArrayList();
ouName = deResult.Properties["ou"][0].ToString();
comboBox1.Items.Insert(1, ouName.ToString());
}
}
catch (Exception ex2)
{
}
}
private void button1_Click(object sender, RoutedEventArgs e) //Error is present in this part
{
string selectou = comboBox1.SelectedValue.ToString();
DirectoryEntry rootDSE = new DirectoryEntry("LDAP://" + selectou);
string defaultContext = rootDSE.Properties["defaultNamingContext"][0].ToString(); //Here is the problem
DirectoryEntry domainRoot = new DirectoryEntry("LDAP://" + selectou);
DirectorySearcher ouSearcher = new DirectorySearcher(selectou);
ouSearcher.SearchScope = SearchScope.Subtree;
ouSearcher.PropertiesToLoad.Add("cn");
ouSearcher.SearchScope = SearchScope.Subtree;
ouSearcher.Filter = "(&(objectClass=user)(objectCategory=person))";
foreach (SearchResult deResult in ouSearcher.FindAll())
{
ArrayList alObjects = new ArrayList();
string dcName = deResult.Properties["cn"][0].ToString();
textBox1.Text = textBox1.Text + dcName.ToString() + "\n";
}
}
Now the problem is occuring at button1_click function. For defaultcontext it throws the following error:
System.Runtime.InteropServices.COMException: The server is not operational.
I'm not able to figure out how to go about this error. Am I missing some kind of assemblies?
Change this line
ouName = deResult.Properties["ou"][0].ToString();
to
ouName = deResult.Properties["distinguishedName"][0].ToString();
and I think you'll be fine
Related
I'm trying to create an AD using with C# and have been getting this error every time
System.DirectoryServices.DirectoryServicesCOMException: 'The specified directory service attribute or value does not exist.
I can't seem to figure out why I'm getting this
private void ccNewHire_Button_Click(object sender, EventArgs e)
{
new Thread(() =>
{
String Password = passwordLabel.Text;
String First = newHireFirstName_TextBox.Text;
String Last = newHireLastName_TextBox.Text;
String Cnname = newHireFirstName_TextBox.Text + " " + newHireLastName_TextBox.Text;
String Username = newHireFirstName_TextBox.Text + "." + newHireLastName_TextBox.Text;
String Ldap = PathtoOURedacted;
DirectoryEntry newUser = new DirectoryEntry("LDAP://PathtoOURedacted");
DirectoryEntry childEntry = newUser.Children.Add("CN=" + Cnname, "user");
newUser.Properties["sAMAccountName"].Value = Username;
newUser.Properties["givenName"].Value = First; // first name
newUser.Properties["sn"].Value = Last; // surname = last name
newUser.Properties["displayName"].Value = Cnname;
newUser.Properties["password"].Value = Password;
newUser.Properties["userAccountControl"].Value = 512;
newUser.CommitChanges();
}).Start();
}
This is your problem:
DirectoryEntry newUser = new DirectoryEntry("LDAP://PathtoOURedacted");
DirectoryEntry childEntry = newUser.Children.Add("CN=" + Cnname, "user");
You're calling the variable newUser, but you're setting it to the OU. So you end up changing the attributes on the OU, not on the actual new user object. Just rename those variables:
DirectoryEntry ou = new DirectoryEntry("LDAP://PathtoOURedacted");
DirectoryEntry newUser = ou.Children.Add("CN=" + Cnname, "user");
Also, this won't work:
newUser.Properties["password"].Value = Password;
The password attribute is unicodePwd, but it has to be set in a very specific way, which the documentation describes. In C#, that looks like this:
newUser.Properties["unicodePwd"].Value = Encoding.Unicode.GetBytes($"\"{Password}\"");
I have an application that uses Windows authentication and I am trying to get logged in users info using their domain IDs.
Part of the data returned is the user's manager's DN (in manager property). I need to query AD again to get manager's info (domain id, email, name, etc.).
I searched and can't find any hint of what I have to use in my filter.
This is what I am using and I always get null returned:
private static DirectoryEntry GetUserDEByDN(string sDN)
{
using (HostingEnvironment.Impersonate())
{
PrincipalContext pc = new PrincipalContext(ContextType.Domain, adUSADomain, adUSAContainer);
//UserPrincipal up = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, UserID);
UserPrincipal qbeUser = new UserPrincipal(pc);
//qbeUser.SamAccountName = UserID.Trim().ToUpper();
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
PrincipalSearchResult<Principal> psr = srch.FindAll();
string sDomain = ConfigurationManager.AppSettings["Domain"].ToString();
string adPath = ConfigurationManager.AppSettings["ADPath"].ToString();
DirectoryEntry de = new DirectoryEntry(adPath);
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
deSearch.Filter = "(&(objectClass=user)(| (cn = " + sDN + ")(dn = " + sDN + ")))";
//deSearch.Filter = "(&(objectClass=user)(SAMAccountName=" + UserID + "))";
deSearch.SearchScope = SearchScope.Subtree;
SearchResult results = deSearch.FindOne();
if (null != results)
{
de = new DirectoryEntry(results.Path);
return de;
}
else
{
return null;
}
}
}
Is it possible to search Active Directory by DN? If so, what I am doing wrong?
This is what worked for me. However, I believe it is supposed to work with objectClass=user but I kept getting null returned. When I changed to distinguishedName = sDN, it worked.
The whole point of this code
DirectoryEntry de = new DirectoryEntry(adPath + "/" + sDN);
is to start the directory search at the user object; there shouldn’t be the need for the additional search of saying which distinguishedName.
private static DirectoryEntry GetUserDEByDN(string sDN)
{
string adPath = ConfigurationManager.AppSettings["ADPath"].ToString();
DirectoryEntry de = new DirectoryEntry(adPath + "/" + sDN);
DirectoryEntry deManager = null;
using (DirectorySearcher Search = new DirectorySearcher())
{
Search.SearchRoot = de;
Search.Filter = "(&(distinguishedName=" + sDN + "))";
//Search.Filter = "(objectClass = user)";
Search.SearchScope = SearchScope.Base;
SearchResult Result = Search.FindOne();
if (null != Result)
deManager = Result.GetDirectoryEntry();
}
return deManager;
}
I am using the below code for login in using Ldap Authentication in ASP.net. However, I don't know how to pass the values from plain-text to this code. I want to run this through button click.
public class LdapAuthentication
{
private string _path;
private string _filterAttribute;
public LdapAuthentication(string path)
{
_path = path;
}
public bool IsAuthenticated(string domain, string username, string pwd)
{
string domainAndUsername = domain + #"\" + username;
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
try
{
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
search.PropertiesToLoad.Add("mail");
SearchResult result = search.FindOne();
if (null == result)
{
return false;
}
//if (result != null)
//{
// string mail = result.Properties["mail"][0].ToString();
//}
// Update the new path to the user in the directory
_path = result.Path;
_filterAttribute = (String)result.Properties["cn"][0];
_filterAttribute = (String)result.Properties["mail"][0];
}
catch (Exception ex)
{
throw new Exception("Error authenticating user. " + ex.Message);
}
return true;
}
public string GetGroups()
{
DirectorySearcher search = new DirectorySearcher(_path);
search.Filter = "(cn=" + _filterAttribute + ")";
search.Filter = "(mail=" + _filterAttribute + ")";
search.PropertiesToLoad.Add("memberOf");
StringBuilder groupNames = new StringBuilder();
try
{
SearchResult result = search.FindOne();
int propertyCount = result.Properties["memberOf"].Count;
String dn;
//int equalsIndex, commaIndex;
for (int propertyCounter = 0; propertyCounter < propertyCount;
propertyCounter++)
{
dn = (String)result.Properties["memberOf"][propertyCounter];
//equalsIndex = dn.IndexOf("=", 1);
//commaIndex = dn.IndexOf(",", 1);
//if (-1 == equalsIndex)
//{
// return null;
//}
//groupNames.Append(dn.Substring((equalsIndex + 1),
// (commaIndex - equalsIndex) - 1));
//groupNames.Append("|");
}
}
catch (Exception ex)
{
throw new Exception("Error obtaining group names. " +
ex.Message);
}
return groupNames.ToString();
}
}
This may be an oversimplification but...
public void LoginButton_Clicked(object sender, EventArgs e)
{
LdapAuthentication auth = new LdapAuthentication("YOURPATH");
if (auth.IsAuthenticated("YOURDOMAIN", txtId.Text, txtPassword.Text))
{
//Login Passed
}
}
I'm assuming you are using WebForms and your username textbox has the ID "txtId", and your password textbox has ID "txtPassword".
If you are not using WebForms the implementation will be different. As spectacularbob mentioned, we can't really answer your question until we know which UI Framework you are using.
I need a small help. I am new to active directory. I want to connect my active directory with c#. Here is the sample code i have wrote.
public void GetConnection()
{
var username = "xxxx";
var domain = "xxxx";
var password = "xxxx";
var path = "LDAP://xxxx/CN=xx";
DirectoryEntry de = new DirectoryEntry(sDomain + "/" + sDefaultOU, sUsername, sServicePassword, AuthenticationTypes.ServerBind);
DirectorySearcher ds = new DirectorySearcher(de);
//Include subtrees
ds.SearchScope = System.DirectoryServices.Protocols.SearchScope.Subtree;
ds.Filter = "(&(objectClass=group))";
//Fetch all results that match the directory entry (domain)
var sr = ds.FindAll();
if (sr != null)
{
MessageBox.Show("success");
}
else
{
MessageBox.Show("error");
}
}
}
The error is:
cannot implicitly convert type 'system.directoryservices.protocols.searchscope' to 'system.directoryservices.searchscope'. an explicit conversion exits.
Can anyone help me?
I have a code to get a list of all the computers within a domain.
Now i need to just get the computers which are within a particular OU and not the rest of the machines.
so here is my code to get all the machines from a domain, this works perfectly fine:
DirectoryEntry entry = new DirectoryEntry("LDAP://" + selectDomain);
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = ("(objectClass=computer)");
mySearcher.SizeLimit = int.MaxValue;
mySearcher.PageSize = int.MaxValue;
foreach (SearchResult resEnt in mySearcher.FindAll())
{
//"CN=SGSVG007DC"
string ComputerName = resEnt.GetDirectoryEntry().Name;
if (ComputerName.StartsWith("CN="))
ComputerName = ComputerName.Remove(0, "CN=".Length);
compList.Add(ComputerName);
}
mySearcher.Dispose();
entry.Dispose();
any suggestions?? thanks.
You just need to add the OU to your directory entry, so instead of taking the root of your domain as being the search path, it takes the domain + OU as being the search path.
See "Enumerating objects in an OU" # http://www.codeproject.com/KB/system/everythingInAD.aspx
I see from your commments that you're having issues here, so let's put this simply - note that this code isn't tested, but should clarify...
string selectDomain = "CN=myCompany,CN=com";
string selectOU = "OU=LosAngeles,OU=America";
DirectoryEntry entry = new DirectoryEntry("LDAP://" + selectOU + "," + selectDomain);
That essentially gives you the string of "LDAP://OU=LosAngeles,OU=America,CN=MyCompany,CN=com" as the new directory entry. You must specify the full LDAP path, not just the OU or the domain.
try to use this Directory entry:
DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://OU={0},{1}", ouName, selectDomain));
i tried all the above.. but it did not work... so this is what i tried and it worked.
i understand this is not the best way but its the only way working for me... any suggestion.. thanks
DirectoryEntry entry = new DirectoryEntry("LDAP://" + selectedDomain);
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = ("(objectClass=organizationalUnit)");
mySearcher.SizeLimit = int.MaxValue;
mySearcher.PageSize = int.MaxValue;
foreach (SearchResult temp in mySearcher.FindAll())
{
Global.logger.Debug("OU = " + temp.Properties["name"][0].ToString());
DirectoryEntry ou = temp.GetDirectoryEntry();
DirectorySearcher mySearcher1 = new DirectorySearcher(ou);
mySearcher1.Filter = ("(objectClass=computer)");
mySearcher1.SizeLimit = int.MaxValue;
mySearcher1.PageSize = int.MaxValue;
if (temp.Properties["name"][0].ToString() == selectedOU)
{
foreach (SearchResult resEnt in mySearcher1.FindAll())
{
//"CN=SGSVG007DC"
string ComputerName = resEnt.GetDirectoryEntry().Name;
Global.logger.Debug("ComputerName = " + resEnt.Properties["name"][0].ToString());
if (ComputerName.StartsWith("CN="))
ComputerName = ComputerName.Remove(0, "CN=".Length);
compList.Add(ComputerName);
}
}
mySearcher1.Dispose();
ou.Dispose();
}
mySearcher.Dispose();
entry.Dispose();