I'm using DirectoryEntry class
Trying to read all users from specific OU and sub OU's.
Following code is part of task
using(DirectoryEntry dEntry = new DirectoryEntry(dn))
using(DirectorySearcher dSearcher = new DirectorySearcher(dEntry))
{
dSearcher.SearchScope = SearchScope.Subtree;
dSearcher.Filter = "(&(objectClass=user) (objectCategory=person))";
foreach(SearchResult in dSearcher.FindAll())
{
//Do something...
}
}
some of sub OU's are protected from reading for current user.
And i got task exception "one or more error accured"
I'm looking for way to check if OU is not accessible and skip it. And to write that OU to log.
I tried following :
public void GetOu(List<MyUser> list, string path)
{
using (DirectoryEntry dEntry = new DirectoryEntry(path))
using(DirectorySearcher dSearcher = new DirectorySearcher(dEntry))
{
dSearcher.SearcherScope = SearchScope.Subtree;
dSearcher.Filter = "(objectClass=organizationalUnit)";
foreach(SearchResult result in dSearcher.FindAll())
{
GetUsersFromOU(list,result.GetDirectoryEntry());
}
}
}
public void GetUsersFromOU(List<MyUser> list,DirectoryEntry ou)
{
using (DirectorySearcher dSearcher = new DirectorySearcher(ou);
dSearcher.SearchScope = SearchScope.OneLevel;
dSearcher.Filter = "(&(objectClass=user)(objectCategory=person))";
foreach (Search result in dSearcher.FindAll())
{
//Do something.... update list...
}
}
Now get no exceptions and skips not accessible OUs.
1.But still can't find what are the "bad ou"s
2.run time is catastrophic...
You will have to make sure that the user running the process has the appropriate permissions to perform the lookup. This will be your Windows account in a desktop application and the account running the application pool in an ASP.NET application.
Related
I'm trying to show, in a ComboBox control, the users from an Active Directory on the network. To do this, I've the next function:
public static List<Usuario> MostrarUsuariosDominio()
{
List<Usuario> rst = new List<Usuario>();
try
{
DirectoryContext dc = new DirectoryContext(DirectoryContextType.Domain, Environment.UserDomainName);
Domain domain = Domain.GetDomain(dc);
DirectoryEntry de = domain.GetDirectoryEntry();
DirectorySearcher adSearcher = new DirectorySearcher(de);
adSearcher.Filter = "(&(objectClass=user)(objectCategory=person))";
adSearcher.PropertiesToLoad.Add("samaccountname");
SearchResult result;
SearchResultCollection iResult = adSearcher.FindAll();
Usuario item;
if (iResult != null)
{
for (int counter = 0; counter < iResult.Count; counter++)
{
result = iResult[counter];
if (result.Properties.Contains("samaccountname"))
{
item = new Usuario();
item.Nombre = (String)result.Properties["samaccountname"][0];
rst.Add(item);
}
}
}
adSearcher.Dispose();
}
catch (Exception ex)
{
Usuario item = new Usuario();
item.Nombre = "No se pudo recuperar la lista de usuarios";
rst.Add(item);
}
return rst;
}
If I run the application in the PC who's domain controller it works fine: the function returns to me all users. But if I run it on another PC, I get the exception:
Specified domain does not exist or couldn't contact with it
Is there any way to recover the users list from another PC?
This line:
DirectoryContext dc = new DirectoryContext(DirectoryContextType.Domain, Environment.UserDomainName);
Tells it to connect to the domain that the current user is logged into. Are you logged in as a domain user?
Maybe check what Environment.UserDomainName is equal to and see if it is right.
If it's right, then it may be a network issue - it can't talk to the domain. Do you need to be connected to VPN?
To get all the users in a Active Directory domain you can use an DirectorySearcher class object to querie to a domain about all the users availables in that domain.
The class DirectorySearcher is contained in System.DirectoryServices namespace and is a class to perform queries against Active Directory Domain Services.
In this page is an example about how to do it:
...
string DomainPath = "LDAP://DC=xxxx,DC=com"
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.PropertiesToLoad.Add("usergroup");
search.PropertiesToLoad.Add("displayname");//first name
SearchResultCollection resultCol = search.FindAll();
...
In DirectorySearcher, create a DirectorySearcher object which searches
for all users in a domain. search.Filter = "(&(objectClass=user)(objectCategory=person))" filters the search.
The search filter syntax looks a bit complicated, but basically it
filters the search results to only include users -> "objectCategory=person" and "objectClass=user" - and excludes disabled
user accounts by performing a bitwise AND of the userAccountControl
flags and the "account disabled" flag.
To point to the local Active Directory domain you can use this:
DirectoryEntry searchRoot = new DirectoryEntry("WinNT://" + Environment.MachineName);
You can combine that example with this code that uses foreach instead of use the for loop in the page example:
foreach (SearchResult result in resultCol)
{
yourComboBox.Items.Add(result.Properties["displayname"]);
}
I left here some pages from the Microsoft MSDN and codeproject.com sites:
DirectorySearcher Class
Get List of Active Directory Users in C#
SearchResultCollection Class
SearchResult Class
SearchResult.Properties Property
I am trying to search for a specific user in the Active Directory, I am using FindAll method. It is giving me an error when I invoke it. How can I solve this issue?
This is the exception I am getting:
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in System.DirectoryServices.dll
SearchResultCollection sResults = null;
try
{
//modify this line to include your domain name
string path = "LDAP://microsistemas.com";
//init a directory entry
DirectoryEntry dEntry = new DirectoryEntry(path);
//init a directory searcher
DirectorySearcher dSearcher = new DirectorySearcher(dEntry);
//This line applies a filter to the search specifying a username to search for
//modify this line to specify a user name. if you want to search for all
//users who start with k - set SearchString to "k";
dSearcher.Filter = "(&(objectClass=user))";
//perform search on active directory
sResults = dSearcher.FindAll();
//loop through results of search
foreach (SearchResult searchResult in sResults)
{
if (searchResult.Properties["CN&"][0].ToString() == "Administrator")
{
////loop through the ad properties
//foreach (string propertyKey in
//searchResult.Properties["st"])
//{
//pull the collection of objects with this key name
ResultPropertyValueCollection valueCollection =
searchResult.Properties["manager"];
foreach (Object propertyValue in valueCollection)
{
//loop through the values that have a specific name
//an example of a property that would have multiple
//collections for the same name would be memberof
//Console.WriteLine("Property Name: " + valueCollection..ToString());
Console.WriteLine("Property Value: " + (string)propertyValue.ToString());
//["sAMAccountName"][0].ToString();
}
//}
Console.WriteLine(" ");
}
}
}
catch (InvalidOperationException iOe)
{
//
}
catch (NotSupportedException nSe)
{
//
}
finally
{
// dispose of objects used
if (sResults != null)
sResults.Dispose();
}
Console.ReadLine();
}
If you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace.
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context - limit to the OU you're interested in
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, null, "DC=microsistemas,DC=com"))
{
// find a user
Principal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");
if(user != null)
{
// do something here....
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
Read more about it here:
MSDN docs on System.DirectoryServices.AccountManagement
Is it possible to read deleted users from Active directory?
Simple and short question.
I want read this info with C# UserPrincipal, but I am not sure if this is possible.
Here's how you can search for deleted users using DirectoryEntry and DirectorySearcher. If it's really trivial for you to get the underlying object as UserPrincipal you can cast user object as UserPrincipal.
public static void searchDeletedUsers()
{
using (DirectoryEntry entry = new DirectoryEntry("LDAP://yourldappath.com"))
{
using (DirectorySearcher searcher = new DirectorySearcher(entry))
{
searcher.Filter = "(&(isDeleted=TRUE)(objectclass=user))";
searcher.Tombstone = true;
var users = searcher.FindAll();
foreach(var user in users)
{
//user will contain the deleted user object
}
}
}
}
I have a ASP.NET Website project and I need to list all the users and their groups on my Windows system. I have set the identity impersonation to true and provided the username and password of the admin in the web.config. Where do I start?
Thanks in advance.
Update:
I have the following code at the moment -
var machine = new DirectoryEntry("WinNT://<IP ADDRESS>");
foreach (DirectoryEntry child in machine.Children)
{
// get the child's group(s).
}
When I debug, I can see the list of users in machine.Children. How do I find the group(s) that this user belongs to?
This article covers how to talk to Active Directory and should get you where you want to go:
http://www.codeproject.com/KB/system/everythingInAD.aspx
To get users, you would do something like this:
public List<string> GetUserList()
{
string DomainName="";
string ADUsername="";
string ADPassword="";
List<string> list=new List<string>();
DirectoryEntry entry=new DirectoryEntry(LDAPConnectionString, ADUsername, ADPassword);
DirectorySearcher dSearch=new DirectorySearcher(entry);
dSearch.Filter="(&(objectClass=user))";
foreach(SearchResult sResultSet in dSearch.FindAll())
{
string str=GetProperty(sResultSet, "userPrincipalName");
if(str!="")
list.Add(str);
}
return list;
}
You probably want to start with the DirectoryEntry and Active Directory support in .net.
Here's a good resource: http://www.codeproject.com/KB/system/everythingInAD.aspx
Local access is similar, even if you're not in a domain:
DirectoryEntry localMachine = new DirectoryEntry("WinNT://" +
Environment.MachineName);
DirectoryEntry admGroup = localMachine.Children.Find("administrators",
"group");
object members = admGroup.Invoke("members", null);
foreach (object groupMember in (IEnumerable)members) {
DirectoryEntry member = new DirectoryEntry(groupMember);
//...
}
How can I check from C# if a local user account (namely the local Administrator account) is active?
What I actually want is a C# replacement for the "Account Active" = "Yes" (or "No") output from the "net user Administrator" command.
I'm afraid this question looks like a duplicate to this one, but I don't know what to pass in for the parameter for the root DirectoryEntry object. Tried different things like "ldap://" + Environment.MachineName, "ldap://127.0.0.1", "WinNT://" + Environment.MachineName, but none of them worked. I get an exception thrown by the searcher.FindAll() call in all three cases.
class Program
{
static void Main(string[] args)
{
// Create the context for the principal object.
PrincipalContext ctx = new PrincipalContext(ContextType.Machine);
UserPrincipal u = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "Administrator");
Console.WriteLine(String.Format("Administrator is enable: {0}", u.Enabled));
}
}
You can query WMI's Win32_UserAccount
This is boilerplate what MS's wmi code creator spits out as a reference;
using System;
using System.Management;
using System.Windows.Forms;
namespace WMISample
{
public class MyWMIQuery
{
public static void Main()
{
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT Disabled FROM Win32_UserAccount WHERE name = 'alexk'");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("-----------------------------------");
Console.WriteLine("Win32_UserAccount instance");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Disabled: {0}", queryObj["Disabled"]);
Console.ReadKey();
}
}
catch (ManagementException e)
{
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
}
}
}
(I'd link the tool but as usual the msdn links are dead)
Try this.
var server = "YOURMACHINENAME";
var username = "Guest";
var de = new DirectoryEntry {Path = "WinNT://" + server + ",computer"};
var result = de.Children
.Cast<DirectoryEntry>()
.First<DirectoryEntry>(d => d.SchemaClassName == "User" && d.Properties["Name"].Value.ToString() == username);
var flags = (int)result.Properties["UserFlags"].Value;
var disabled = (flags & 2) == 2;
This isn't quite the same but they use DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("WinNT://{0}/{1}", computerName, username)); Would that help?
Considering it's a local user, you need to call the win32 api funcion NetGetUserInfo to get what you need.
The example in pinvoke.net is almost what you need, however you need to change the level parameter to 2 to get the neccesary info