I am trying to query AD to get the list of users
The query is success, and I am getting 90 records as results, the problem is that I am expecting more over than 15000 records.
Before I go to the IT and check the right domain path, it would be great if I am sure that my code is not the issue.
Thank you for every much
Already tried changing the search page size
DataTable resultSet = new DataTable();
resultSet.Columns.Add(new DataColumn("mail", typeof (string)));
resultSet.Columns.Add(new DataColumn("username", typeof (string)));
resultSet.Columns.Add(new DataColumn("displayname", typeof (string)));
try
{
string DomainPath = "LDAP://MyDomain";
DirectoryEntry searchRoot = new DirectoryEntry(DomainPath);
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.Filter = "(&(objectClass=user)(objectCategory=person))";
search.PropertiesToLoad.Add("samaccountname");
search.PropertiesToLoad.Add("mail");
search.PageSize = 1001;
search.PropertiesToLoad.Add("displayname");//first name
SearchResult result;
SearchResultCollection resultCol = search.FindAll();
if (resultCol != null)
{
for (int counter = 0; counter < resultCol.Count; counter++)
{
result = resultCol[counter];
if (result.Properties.Contains("samaccountname") && result.Properties.Contains("mail") && result.Properties.Contains("displayname"))
{
var row = resultSet.NewRow();
resultSet.Rows.Add(row);
var Email = (String) result.Properties["mail"][0];
row["mail"] = Email;
var UserName = (String) result.Properties["samaccountname"][0];
row["username"] = UserName;
var DisplayName = (String) result.Properties["displayname"][0];
row["displayname"] = DisplayName;
row.AcceptChanges();
}
}
resultCol.Dispose();
}
}
catch (Exception ex)
{
App.Log.Write("Exception while read user from AD: " + ex.ToString());
}
return resultSet;
Expected over 15000 records getting 90 only
Related
I am having this code that returns list of users and groups from the Active Directory
public ArrayList GetADGroupUsers(string groupNames)
{
string[] strGrpNames = groupNames.Split(new char[] { ',' });
string strTeamList = string.Empty;
ArrayList userNames = new ArrayList();
string ADPassword = ConfigurationManager.AppSettings["ADPassword"];
IAAccess_Transaction.drms_dataaccess drmsda = new IAAccess_Transaction.drms_dataaccess();
string domainAndUsername = ConfigurationManager.AppSettings["domain"] + #"\" + ConfigurationManager.AppSettings["ADUserName"];
string decriptedADPassword = drmsda.Decrypt(ADPassword);
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, decriptedADPassword);
//Bind to the native AdsObject to force authentication.
object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
foreach (string strGrp in strGrpNames)
{
search.Filter = String.Format("(cn={0})", strGrp);
search.PropertiesToLoad.Add("member");
SearchResult result = search.FindOne();
if (result != null)
{
for (int counter = 0; counter <
result.Properties["member"].Count; counter++)
{
string user = (string)result.Properties["member"][counter];
userNames.Add(user);
}
}
}
return userNames;
}
This code retrieves BOTH, users AND group as shown on the screenshot. How can I modify this code to retrieve JUST users, NOT groups?
In order to include the nested group members, you need to lookup each entry and find out if it is a group or user. If it is a group, you can add to the groups you are already processing. Since C#/.Net doesn't have a built-in Deque class, I used LinkedList<T> instead.
public List<string> GetADGroupUsers(string groupNames) {
LinkedList<string> strGrpNames = new(groupNames.Split(','));
List<string> userNames = new();
string ADPassword = ConfigurationManager.AppSettings["ADPassword"];
string domainAndUsername = ConfigurationManager.AppSettings["domain"] + #"\" + ConfigurationManager.AppSettings["ADUserName"];
string decryptedADPassword = drmsda.Decrypt(ADPassword);
DirectoryEntry entry = new(_path, domainAndUsername, decryptedADPassword);
//Bind to the native AdsObject to force authentication.
object obj = entry.NativeObject;
DirectorySearcher groupSearcher = new(entry);
groupSearcher.PropertiesToLoad.Add("member");
DirectorySearcher userSearcher = new(entry);
userSearcher.PropertiesToLoad.Add("groupType");
while (strGrpNames.Count > 0) {
string strGrp = strGrpNames.First();
strGrpNames.RemoveFirst();
groupSearcher.Filter = $"(cn={strGrp})";
SearchResult result = groupSearcher.FindOne();
if (result != null) {
var members = result.Properties["member"];
for (int counter = 0; counter < members.Count; ++counter) {
var user = (string)members[counter];
var userCN = user.Substring(user.IndexOf('=')+1).Substring(0,user.IndexOf(',')-3);
userSearcher.Filter = $"(cn={userCN})";
SearchResult userProperties = userSearcher.FindOne();
var userGroupType = userProperties.Properties["groupType"];
if (userGroupType != null && userGroupType.Count > 0) // group
strGrpNames.AddFirst(userCN);
else
userNames.Add(user);
}
}
}
return userNames;
}
I am trying to get result from DataTable but I am stuck and have no idea what to do.
I have public static DataTable VratiKorisnike() which needs to return DataTable resultTable as result because my result is store in resultTable.
SO far my function is here
public static DataTable VratiKorisnike()
{
List<Korisnik> lstADUsers = new List<Korisnik>();
string sDomainName = "saos";
string DomainPath = "LDAP://" + sDomainName;
string output = #"C:\output.txt";
DirectoryEntry searchRoot = new DirectoryEntry(DomainPath);
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.Filter = "(&(objectClass=user)(objectCategory=person))";
search.PropertiesToLoad.Add("samaccountname");
search.PropertiesToLoad.Add("usergroup");
search.PropertiesToLoad.Add("displayname");
search.PropertiesToLoad.Add("userAccountControl");
search.PropertiesToLoad.Add("PasswordExpirationDate");
//search.PropertiesToLoad.Add("DomainGroup");
DataTable resultsTable = new DataTable();
resultsTable.Columns.Add("samaccountname");
resultsTable.Columns.Add("usergroup");
resultsTable.Columns.Add("displayname");
resultsTable.Columns.Add("userAccountControl");
resultsTable.Columns.Add("PasswordExpirationDate");
//resultsTable.Columns.Add("DomainGroup");
SearchResult result;
SearchResultCollection resultCol = search.FindAll();
if (resultCol != null)
{
for (int counter = 0; counter <= (resultCol.Count - 1); counter++)
{
string UserNameEmailString = string.Empty;
result = search.FindOne();
if ((result.Properties.Contains("samaccountname") && result.Properties.Contains("usergroup")))
{
Korisnik korisnik = new Korisnik();
korisnik.Ime = ((string)(result.Properties["samaccountname"][0]));
korisnik.Prezime = ((string)(result.Properties["displayname"][0]));
korisnik.AccountExpired = (DateTime)result.Properties["userAccountControl"][0];
korisnik.PassNevExp = ((bool)result.Properties["PasswordExpirationDate"][0]);
korisnik.DomenskaGrupa = ((string)(result.Properties["DomainGroup"][0]));
DataRow dr = resultsTable.NewRow();
dr["samaccountname"] = korisnik.Ime;
dr["displayname"] = korisnik.Prezime;
dr["userAccountControl"] = korisnik.AccountExpired;
dr["PasswordExpirationDate"] = korisnik.PassNevExp;
dr["DomainGroup"] = korisnik.DomenskaGrupa;
resultsTable.Rows.Add(dr);
lstADUsers.Add(korisnik);
}
}
var json = JsonConvert.SerializeObject(resultCol, Formatting.Indented);
var res = json;
Console.WriteLine(resultCol);
Console.ReadLine();
File.WriteAllText(output, json);
}
return resultsTable;
}
When I call function to Main I get error
Foreach statement cannot operate on variables of type 'DataTable'
because 'DataTable' does not contain a public instance definition for
'GetEnumerator'
foreach (Korisnik korisnik in VratiKorisnike())
{
Console.WriteLine(korisnik);
}
I try something like this:
foreach(DataTable dt in VratiKorisnike())
{
Console.WriteLine(dt);
}
The error is VratiKorisnike()
Any idea how to resolve this issue ?
To use a DataTable as an IEnumerable<DataRow>, you need to use Linq To DataSet, in perticular AsEnumerable
foreach (DataRow row in VratiKorisnike().AsEnumerable())
{
string displayName = row.Field<string>("displayname")
...
}
You need to use the Rows property:
foreach (var korisnik in VratiKorisnike().Rows)
It Represents a collection of rows for a DataTable, and . Actually it will compiles like this and as you can see, because of GetEnumerator you can use your loop with that:
IEnumerator enumerator = VratiKorisnike().Rows.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
DataRow value = (DataRow)enumerator.Current;
Console.WriteLine(value);
}
}
finally
{
IDisposable disposable = enumerator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
I have a procedure that retrieves the user node out of AD:
public static void ConnectActiveDirectory()
{
List<string> lstGroups = new List<string>();
DirectoryEntry entry;
string user = "username";
string server = ConfigurationManager.AppSettings["ActiveDirectory.Server"];
entry = new DirectoryEntry(#"LDAP://" + server);
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "sAMAccountName=" + user;
searcher.PropertiesToLoad.Add("MemberOf");
SearchResult result = searcher.FindOne();
}
The idea is to save all the groups in the list of strings without doing something like:
foreach (ResultPropertyValueCollection s in result.Properties.Values)
{
string groupname = null;
for (int i = 0; i < s.Count; i++)
{
dn = s[i].ToString();
equalsIndex = dn.IndexOf("=", 1);
commaIndex = dn.IndexOf(",", 1);
groupname = dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1);
lstGroups.Add(groupname);
}
}
Is there any method that I can use in 'DirectorySearcher' Class?
Also, is there any way to delete the first Hashtable? the adspath one from the SearchResult object.
Instead of parsing the distinguished name by yourself, you can use the DirectoryEntry object to ask AD for the display name. For example:
var directoryEntry = new DirectoryEntry(#"LDAP://address");
var directorySearcher = new DirectorySearcher(directoryEntry);
directorySearcher.Filter = "samaccountname=user";
directorySearcher.PropertiesToLoad.Add("memberOf");
var result = directorySearcher.FindOne();
foreach (var i in result.Properties["memberOf"])
{
var group = new DirectoryEntry(#"LDAP://" + i);
Console.WriteLine(group.Properties["DisplayName"]);
}
I am working on implementing Search using Lucene.Net in my E Commerce site. I want to Sort by result depending on user selected criterion. It might be Name,Price,Discount,NewArrivals etc
My Code
var sortBy = new Lucene.Net.Search.Sort(new Lucene.Net.Search.SortField("Name", Lucene.Net.Search.SortField.STRING, true));
//var parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_30, "Name", analyzer);
//Query searchQuery = parser.Parse(query);
//TopDocs hits = searcher.Search(searchQuery, int.MaxValue);
//Sort sort=new Sort
//TopDocs hits = searcher.Search(QueryMaker(query, searchfields, storeId), int.MaxValue);
TopFieldDocs hits = searcher.Search(QueryMaker(query, searchfields, storeId),null,int.MaxValue,sortBy);
int results = hits.TotalHits;
Product searchResult = null;
if (results < limit)
limit = results;
//if (limit == 0)
// limit = int.MaxValue;
for (int i = (pagenumber*limit) + 1; i <= ( ( pagenumber * limit ) + limit); i++)
{
try
{
Document doc = searcher.Doc(hits.ScoreDocs[i-1].Doc);
searchResult = new Product();
searchResult.Id = Convert.ToInt32(doc.Get("Id"));
searchResult.Name = doc.Get("Name");
searchResult.SeName = doc.Get("SeName");
searchResult.StoreId = Convert.ToInt32(doc.Get("StoreId"));
searchResults.Add(searchResult);
searchResult = null;
}
catch (Exception ae)
{
}
}
But this doesnt give me expected result and does not sort products using its Name
Any Solutions
I need to get sAMAccountName by passing EmployeeId to the active directory.
Please help me.
I don't know what is the EmployeeId for you but here is how to access all the users and display some fields :
Domain domain = Domain.GetCurrentDomain();
var searchRoot = domain.GetDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.Filter = "(&(objectClass=user)(objectCategory=person))";
search.PropertiesToLoad.Add("sAMAccountName");
search.PropertiesToLoad.Add("userPrincipalName");
search.PropertiesToLoad.Add("displayName");
SearchResultCollection results = search.FindAll();
if (results != null)
{
foreach(SearchResult result in results)
{
Console.WriteLine("{0} ({1}) sAMAccountName={2}",
result.Properties["displayName"].OfType<object>().FirstOrDefault(),
result.Properties["userPrincipalName"].OfType<object>().FirstOrDefault(),
result.Properties["sAMAccountName"].OfType<object>().FirstOrDefault());
}
}
To discover all the fields present on your schema you can use AdExplorer.
Try this (with many thanks to VirtualBlackFox)
string employeeId ="someEmployeeId";
Domain domain = Domain.GetCurrentDomain();
var searchRoot = domain.GetDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.PropertiesToLoad.Add("EmployeeID");
search.PropertiesToLoad.Add("sAMAccountName");
search.Filter = String.Format("(&(objectCategory=person)(EmployeeID={0}))", employeeId );
SearchResult searchResult =search.FindOne();
if (searchResult != null)
{
object o = searchResult.Properties["sAMAccountName"].OfType<object>().FirstOrDefault();
if (o != null)
{
string sAMAccountName= o.ToString();
}
}