I am trying to get the list of local users of a computer using the following code.
internal void GetUsers()
{
try
{
List<string> adUsers = new List<string>();
DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://" + Environment.MachineName);
foreach (DirectoryEntry child in directoryEntry.Children)
{
if (child.SchemaClassName.Equals("User", StringComparison.OrdinalIgnoreCase))
{
adUsers.Add(child.Name);
}
}
}
catch (Exception ex)
{
//Exception
}
}
This code works fine in my computer. However, when I tested it on a few other computers, the following system users were included in the list:
ASPNET,
HelpAssistant
Could some one throw some light on how I can get rid of these system users and get only users who actually log in, ie, normal users.
Thanks,
Ram
Not an answer as such, but some suggestions that might help.
I think the problem is that those accounts aren't real system accounts, so might not be so easy to distinguish.
You could look at the WMI classes Win32_UserAccount and Win32_UserProfile and see if there are any properties in there that might indicate which user accounts are normal ones and which ones are the ones you mention. Specifically, maybe the 'SIDType' or 'AccountType' properties of Win32_UserAccount or maybe the Special property of the Win32_UserProfile class.
Might be other WMI classes that might be worth looking at as well.
Or there might be some way that you can query if a user account has the interactive logon right (which I assume those two accounts might not have normally).
Have you tried enumerating the Properties collection on DirectoryEntry?
using (DirectoryEntry dirEntry = new DirectoryEntry(strchild))
{
foreach (string strPropertyName in dirEntry.Properties.PropertyNames)
{
Console.WriteLine(strPropertyName + " " + dirEntry.Properties[strPropertyName].Value.ToString());
}
}
Other than that, you may have to do an LDAP search on Active Directory to match the UserName you have found to an ActiveDirectory user.
Have a look at this article.
http://www.codeproject.com/KB/system/everythingInAD.aspx
Have fun.
The following code will get you the local users that actually have local accessible folders.
var localDrives = Environment.GetLogicalDrives();
var localUsers = new List<string>();
var query = new SelectQuery("Win32_UserAccount") { Condition = "SIDType = 1 AND AccountType = 512" };
var searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject envVar in searcher.Get())
{
foreach (string drive in localDrives)
{
var dir = Path.Combine(String.Format("{0}Users", drive), envVar["name"].ToString());
if (Directory.Exists(dir))
{
localUsers.Add(envVar["name"].ToString());
}
}
}
Related
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);
//...
}
I need to enumerate all user profiles on a local computer and list them in a combo box. Any special accounts need to be filtered out. I'm only concerned about actual user profiles on the computer where the app is running. I have done some searching but I haven't found a clear answer posted anywhere. I did find some code that might work but SelectQuery and ManagementObjectSearcher are displaying errors in VS and I'm not sure what I need to do to make this work.
using System.Management;
SelectQuery query = new SelectQuery("Win32_UserAccount");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject envVar in searcher.Get())
{
Console.WriteLine("Username : {0}", envVar["Name"]);
}
By saying "SelectQuery and ManagementObjectSearcher are displaying errors" I guess you didn't reference the System.Management dll.
You should right click References in your solution and add System.Management.
Then, with your using statement, the errors should disappear.
Anyway, including the error next time will assist everyone to help you :)
The mentioned code is great but when I tried on a machine connected to a Active Directory Domain all the usernames where returned for the domain. I was able to tweak the code a bit to only return the users that actually have a local directory on the current machine. If a better C# developer can refactor the code to make it cleaner - please help!
var localDrives = Environment.GetLogicalDrives();
var localUsers = new List<string>();
var query = new SelectQuery("Win32_UserAccount") { Condition = "SIDType = 1 AND AccountType = 512" };
var searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject envVar in searcher.Get())
{
foreach (string drive in localDrives)
{
var dir = Path.Combine(String.Format("{0}Users", drive), envVar["name"].ToString());
if (Directory.Exists(dir))
{
localUsers.Add(envVar["name"].ToString());
}
}
}
Once you have the localUsers variable you can set this as the data source to your ComboBox control of our choice.
So, I'm kind of stuck here...
I'm writing a program that should be able to list all users in the local administrator group on a MS Windows Server 2008 R2.
The problem here is that I'm only allowed to use .NET 2.0 - so I'm not able to use the GroupPrincipal Class... Which would have made this a really easy task.
Any pointers would be appriciated!
Cheers!
Jeez!
Don't know what I was thinking really - it's so simple!
All creds to Masoud Tabatabaei - found the following codesnippet on:
http://csharptuning.blogspot.se/2007/09/how-to-get-list-of-windows-user-in-c.html
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);
lstUsers.Items.Add(member.Name);
}
Did you try WMI ?
for example
ManagementObjectSearcher search = new ManagementObjectSearcher(#"SELECT * FROM Win32_UserAccount where LocalAccount = true");
ManagementObjectCollection userList = search.Get();
foreach (ManagementObject user in userList)
{
Console.WriteLine("User name: {0}, Full Name: {1}",
user["Name"].ToString(), user["FullName"].ToString());
}
Will give you a list of users in local SAM. You can add other attributes to the query and refine your list.
Do not forget to add a reference to System.Management.dll
If your are still looking for an answer, here:
If you'd like to get the administrator group, you can use this code:
public static DirectoryEntry GetLocalAdminstratorGroup()
{
using (var WindowsActiveDirectory = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer"))
{
return WindowsActiveDirectory.Children.Find(GetLocalizedAdministratorGroupName(), "group");
}
}
//Localized == Language Independent
public static string GetLocalizedAdministratorGroupName()
{
//For English Windows version, this equals "BUILTIN\Administrators".
var adminGroupName = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null).Translate(typeof(NTAccount)).Value;
//Remove the "BUILTIN\" part, get the local name of the group
return adminGroupName.Split('\\')[1];
}
If you'd also like to enumerate it (like you need a username), you can do this, using the methods before:
object members = AdminGroup.Invoke("members", null);
foreach (object groupMember in (IEnumerable)members)
{
DirectoryEntry member = new DirectoryEntry(groupMember);
Console.WriteLine(member.Name);
}
Hello I'm stuck trying to add a function to my Windows forms program that allows a user to type in a textbox what computer or computers they would like to search for in Active Directory. The user would input the search string in a textbox then hit a button and the computers that match that search result would appear in a separate search box. Here is my code so far.
I would also like each computer name to be on a separate line such as:
computername1
computername2
computername3
Thanks!
This is what inside the button looks like:
List<string> hosts = new List<string>();
DirectoryEntry de = new DirectoryEntry();
de.Path = "LDAP://servername";
try
{
string adser = txtAd.Text; //textbox user inputs computer to search for
DirectorySearcher ser = new DirectorySearcher(de);
ser.Filter = "(&(ObjectCategory=computer)(cn=" + adser + "))";
ser.PropertiesToLoad.Add("name");
SearchResultCollection results = ser.FindAll();
foreach (SearchResult res in results)
//"CN=SGSVG007DC"
{
string computername = res.GetDirectoryEntry().Properties["Name"].Value.ToString();
hosts.Add(computername);
//string[] temp = res.Path.Split(','); //temp[0] would contain the computer name ex: cn=computerName,..
//string adcomp = (temp[0].Substring(10));
//txtcomputers.Text = adcomp.ToString();
}
txtcomputers.Text = hosts.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
de.Dispose();//Clean up resources
}
If you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on the System.DirectoryServices.AccountManagement namespace
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// find a computer
ComputerPrincipal computer = ComputerPrincipal.FindByIdentity(ctx, "SomeComputerName");
if (computer != null)
{
// do something here....
}
}
If you don't need to find a single computer, but search for a whole list of computers, you can use the new PrincipalSearcher interface, which basically allows you to set up a "QBE" (query-by-example) object you're looking for, defining the search criteria, and then search for matches for those criteria.
The new S.DS.AM namespace makes it really easy to play around with users and groups in AD!
I have the following method used for searching for a User Group either on the local computer (done first) or in the Current Forest.
public string FindUserGroup(string group)
{
//Search local computer
using (DirectorySearcher searcher = new DirectorySearcher(new DirectoryEntry()))
{
searcher.Filter = "(&(objectClass=group)(|(cn=" + group + ")(dn=" + group + ")))";
SearchResult result = searcher.FindOne();
if (result != null)
return TranslateDirectoryEntryPath(result.GetDirectoryEntry().Path);
}
//Search current forest
Forest forest = Forest.GetCurrentForest();
foreach (Domain domain1 in forest.Domains)
{
using (DirectorySearcher searcher = new DirectorySearcher(domain1.GetDirectoryEntry()))
{
searcher.Filter = "(&(objectClass=group)(|(cn=" + group + ")(dn=" + group + ")))";
SearchResult result = searcher.FindOne();
if (result != null)
return TranslateDirectoryEntryPath(result.GetDirectoryEntry().Path);
}
}
return string.Empty;
}
My problem is that we as an example have say "domain.local" and "mydomain.local", and my current login is bound to "domain.local", then using below won't be able to find anything in "mydomain.local", even if I through the Windows User Interface is able to.
How can I search all viewable providers from my computers perspective when I don't nessesarily know them all? Do I REALLY have to do the Registry Work my self?
Edit:
One difference in the 2 domains is the "level" they are on when I in an object browser dialog chooses "Locations", it layouts as:
Computer
Entire Direction
domain.local
mydomain.local
So "mydomain.local" excists outside what is referred to as "Entire Directory", yet my computer can locate it, if that makes any difference?
I don't see a problem as this code here would have already be binded to the other domains.
foreach (Domain domain1 in forest.Domains)
{
using (DirectorySearcher searcher = new DirectorySearcher(domain1.GetDirectoryEntry()))
{
Are you trying to say that later on you're binding a DirectoryEntry on your own, and you can't find objects from other domain?