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?
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}\"");
This code works perfectly to get the phone number from Active Directory using the username and password
public string GetPhone(string domain, string username, string pwd)
{
_path = "LDAP://" + domain;
string domainAndUsername = domain + #"\" + username;
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
string telephoneNumber = string.Empty;
try
{
object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
SearchResult result = search.FindOne();
var myEntry = result.GetDirectoryEntry();
telephoneNumber = myEntry.Properties["telephoneNumber"].Value.ToString();
}
catch (Exception ex)
{
throw new Exception("Error obtaining phone number. " + ex.Message);
}
return telephoneNumber;
}
However, I have access to the user password only on the login page. I do have the User context being generated though that is accessible from anywhere within the application (Context.User which is of System.Security.Principal.IPrincipal type)
Thus, how can I get the phone from Active Directory using an already available Context.User object?
Thank you very much in advance
The User object you get will have the SID of the user. With that, you can use the SID binding LDAP path in DirectoryEntry: LDAP://<SID=XXXXX>
var user = new DirectoryEntry(
$"LDAP://<SID={((WindowsIdentity) HttpContext.User.Identity).User.Value}>");
user.RefreshCache(new [] { "telephoneNumber" });
var telephoneNumber = user.Properties["telephoneNumber"]?.Value as string;
The use of RefreshCache is to load only the telephoneNumber attribute. Otherwise, when you first use .Properties, it will retrieve every attribute, which is a waste of time and bandwidth.
Looks like I overcomplicated everything and solution is quite simple
private void SetPhone()
{
DirectoryEntry entryDomain = new DirectoryEntry("LDAP://" + domain);
DirectorySearcher ds = new DirectorySearcher(entryDomain);
string lastName = Context.User.Identity.Name.Split(' ')[Context.User.Identity.Name.Split(' ').Length - 1];
ds.Filter = "(sn=" + lastName + ")";
SearchResult sr = ds.FindOne();
string telephoneNumber = sr.Properties["telephoneNumber"][0].ToString();
telephoneNumber = telephoneNumber.Insert(0, "(").Insert(4, ")").Insert(5, " ").Insert(9, "-");
Session["UserPhone"] = String.Format("{0:(###) ###-####}", telephoneNumber); ;
}
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'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
I am having issues connecting to a public LDAP using PrincipalContext. I can get directory entry working fine:
string sDomain = "LDAP://ldap.itd.umich.edu:389";
string sDefaultOU = "ou=System Groups,ou=Groups,dc=umich,dc=edu";
string sServiceUser = "cn=Directory Manager,o=University of Michigan,c=us";
string sServicePassword = "";
DirectoryEntry de = new DirectoryEntry(sDomain + "/" + sDefaultOU, sServiceUser, sServicePassword, AuthenticationTypes.ServerBind);
DirectorySearcher ds = new DirectorySearcher(de);
SearchResult sr = ds.FindOne();
But when I try to do the same thing with PrincipalContext I get a null reference error:
sDomain = "ldap.itd.umich.edu";
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sDefaultOU, sServiceUser, "");
Any ideas what I am doing wrong?