How to remove windows user account using C#?
Clause Thomsen was close, you need to pass the DirectoryEntry.Remove method a DirectoryEntry paramenter and not a string, like:
DirectoryEntry localDirectory = new DirectoryEntry("WinNT://" + Environment.MachineName.ToString());
DirectoryEntries users = localDirectory.Children;
DirectoryEntry user = users.Find("userName");
users.Remove(user);
Something like this should do the trick(not tested):
DirectoryEntry localMachine = new DirectoryEntry("WinNT://" + Environment.MachineName);
DirectoryEntries entries = localMachine.Children;
DirectoryEntry user = entries.Remove("User");
entries.CommitChanges();
Alternatively using System.DirectoryServices.AccountManagement in .NET 3.5:-
http://msdn.microsoft.com/en-us/library/bb924557.aspx
using System;
using System.DirectoryServices.AccountManagement;
namespace AdministratorsGroupSample
{
class Program
{
static void Main(string[] args)
{
PrincipalContext ctx = new PrincipalContext(ContextType.Machine);
GroupPrincipal grpp = new GroupPrincipal(ctx);
UserPrincipal usrp = new UserPrincipal(ctx);
PrincipalSearcher ps_usr = new PrincipalSearcher(usrp);
PrincipalSearchResult<Principal> fr_usr = ps_usr.FindAll();
PrincipalSearcher ps_grp = new PrincipalSearcher(grpp);
PrincipalSearchResult<Principal> fr_grp = ps_grp.FindAll();
foreach (var usr in fr_usr)
{
Console.WriteLine($"Name:{usr.Name} SID:{usr.Sid} Desc:{usr.Description}");
Console.WriteLine("\t Groups:");
foreach (var grp in usr.GetGroups())
{
Console.WriteLine("\t" + $"Name:{grp.Name} SID:{grp.Sid} Desc:{grp.Description}");
}
Console.WriteLine();
}
Console.WriteLine();
foreach (var grp in fr_grp)
{
Console.WriteLine($"{grp.Name} {grp.Description}");
}
Console.ReadLine();
}
private void Delete(string userName)
{
PrincipalContext ctx = new PrincipalContext(ContextType.Machine);
UserPrincipal usrp = new UserPrincipal(ctx);
usrp.Name = userName;
PrincipalSearcher ps_usr = new PrincipalSearcher(usrp);
var user = ps_usr.FindOne();
user.Delete();
}
}
}
Related
Im trying to get all users of a particular group in AD but i am getting Exception : "The specified directory service attribute or value does not exist."
//using (var principalContext = new PrincipalContext(ContextType.Domain))
using (var principalContext = new PrincipalContext(ContextType.Domain, "domainName"))
{
//using (var group = GroupPrincipal.FindByIdentity(context, windowsGroup.TrimEnd('*')))
using (var groupPrincipal = GroupPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, "groupName"))
{
if (groupPrincipal != null)
{
var users = groupPrincipal.GetMembers();
foreach (UserPrincipal userPrincipal in users)
{
//user variable has the details about the user
}
}
}
}
use container to specify your root
using (var principalContext = new PrincipalContext(ContextType.Domain, "TEST.COM", "DC=TEST,DC=COM"))
{
//using (var group = GroupPrincipal.FindByIdentity(context, windowsGroup.TrimEnd('*')))
using (var groupPrincipal = GroupPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, "groupName"))
{
if (groupPrincipal != null)
{
var users = groupPrincipal.GetMembers();
foreach (UserPrincipal userPrincipal in users)
{
//user variable has the details about the user
}
}
}
}
I am using SharePoint 2010, and I can't seem to get this code to return anything in our production environment. The server is set up for Claims Based Authentication.
private string GetADName(string userID)
{
try
{
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// define a "query-by-example" principal - here, we search for a UserPrincipal
// and with the first name (GivenName) of "Bruce" and a last name (Surname) of "Miller"
UserPrincipal qbeUser = new UserPrincipal(ctx);
qbeUser.SamAccountName = userID;
// create your principal searcher passing in the QBE principal
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
// find all matches
foreach (var found in srch.FindAll())
{
return found.Name;
}
}
catch (Exception ex)
{
this.lblErrors.Text = ex.Message + "<br />\r\n" + ex.StackTrace;
}
return "";
}
I had to use HostingEnvironment.Impersonate()
private string GetADName(string userID)
{
try
{
using (HostingEnvironment.Impersonate())
{
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
UserPrincipal qbeUser = new UserPrincipal(ctx);
qbeUser.SamAccountName = userID.ToLower();
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
foreach (var found in srch.FindAll())
{
if (found.SamAccountName.ToLower() == userID.ToLower())
{
return found.Name;
}
}
}
}
catch (Exception ex)
{
}
return "";
}
I need to provide a search on Active Directory using filters such as Display name, Telephone and Department. Display name and Telephone are easy but I'm stuck on department. This is the bit that works:
using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
{
UserPrincipal userPrincipal = new UserPrincipal(context);
if (txtDisplayName.Text != "")
userPrincipal.DisplayName = "*" + txtDisplayName.Text + "*";
using (PrincipalSearcher searcher = new PrincipalSearcher(userPrincipal))
{
foreach (Principal result in searcher.FindAll())
{
DirectoryEntry directoryEntry = result.GetUnderlyingObject() as DirectoryEntry;
DataRow drName = dtProfile.NewRow();
drName["displayName"] = directoryEntry.Properties["displayName"].Value;
drName["department"] = directoryEntry.Properties["department"].Value;
dtProfile.Rows.Add(drName);
}
}
}
I was hoping that I could just add something like:
DirectoryEntry userDirectoryEntry = userPrincipal.GetUnderlyingObject() as DirectoryEntry;
if (ddlDepartment.SelectedValue != "")
userDirectoryEntry.Properties["title"].Value = ddlDepartment.SelectedValue;
But that doesn't work. Anyone know how I can do this?
Edit:
I'm an idiot, changed the search term and found the answer. The extra fields are called attibutes. Thanks Raymund Macaalay for your blog article on extending Principals.
My extended UserPrincipal:
[DirectoryObjectClass("user")]
[DirectoryRdnPrefix("CN")]
public class UserPrincipalExtended : UserPrincipal
{
public UserPrincipalExtended(PrincipalContext context) : base(context)
{
}
[DirectoryProperty("department")]
public string department
{
get
{
if (ExtensionGet("department").Length != 1)
return null;
return (string)ExtensionGet("department")[0];
}
set { this.ExtensionSet("department", value); }
}
}
Since you've already extended the UserPrincipal to include the Department attribute, you'll need to use that extended version of the user principal when you want to search.
Try this:
using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
{
UserPrincipalExtended userPrincipal = new UserPrincipalExtended(context);
if (txtDisplayName.Text != "")
{
userPrincipal.DisplayName = "*" + txtDisplayName.Text + "*";
}
if (!string.IsNullOrEmpty(txtDepartment.Text.Trim())
{
userPrincipal.department = txtDepartment.Text.Trim();
}
using (PrincipalSearcher searcher = new PrincipalSearcher(userPrincipal))
{
foreach (Principal result in searcher.FindAll())
{
UserPrincipalExtended upe = result as UserPrincipalExtended;
if (upe != null)
{
DataRow drName = dtProfile.NewRow();
drName["displayName"] = upe.DisplayName;
drName["department"] = upe.department;
dtProfile.Rows.Add(drName);
}
}
}
}
How do I search all the user accounts in a domain in .NET?
Not the computer names in the domain, but the user accounts, that's what you are using to log on Windows.
You can try the following.
PrincipalContext ctx = new PrincipalContext(ContextType.Machine,Environment.MachineName);
UserPrincipal user = new UserPrincipal(ctx);
user.Name = "*";
PrincipalSearcher ps = new PrincipalSearcher();
ps.QueryFilter = user;
PrincipalSearchResult<Principal> result = ps.FindAll();
foreach (Principal p in result)
{
using (UserPrincipal up = (UserPrincipal)p)
{
MessageBox.Show(up.Name);
}
}
Or this:
using System.Management;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
SelectQuery query = new SelectQuery("Win32_UserAccount");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject envVar in searcher.Get())
{
Console.WriteLine("Username : {0}", envVar["Name"]);
}
Console.ReadLine();
}
See also How to list all Windows Users.
You can use something like the following:
List<string> LdapUsers = new List<string>();
if (String.IsNullOrWhiteSpace(domain))
{
string username = WindowsIdentity.GetCurrent().Name;
domain = username.Substring(0, username.IndexOf("\\"));
}
PrincipalContext context;
if (!String.IsNullOrWhiteSpace(user) && !String.IsNullOrWhiteSpace(password) && !String.IsNullOrWhiteSpace(domain))
context = new PrincipalContext(ContextType.Domain, domain, user, password);
if (!String.IsNullOrWhiteSpace(domain))
context = new PrincipalContext(ContextType.Domain, domain);
else
context = new PrincipalContext(ContextType.Domain);
UserPrincipal userP = new UserPrincipal(context);
userP.Enabled = true;
PrincipalSearcher pS = new PrincipalSearcher();
pS.QueryFilter = userP;
PrincipalSearchResult<Principal> result = pS.FindAll();
foreach (Principal p in result)
LdapUsers.Add(domain + "\\" + p.SamAccountName);
One more way to search for domain users:
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using (var domain = Domain.GetCurrentDomain())
using (var directoryEntry = domain.GetDirectoryEntry())
using (var directorySearcher = new DirectorySearcher(directoryEntry, "(&(objectCategory=person)(objectClass=user))"))
{
directorySearcher.PageSize = 1000;
using (var searchResults = directorySearcher.FindAll())
{
foreach (SearchResult searchResult in searchResults)
{
using (var userEntry = searchResult.GetDirectoryEntry())
{
Console.WriteLine(userEntry.Properties["cn"][0]);
}
}
}
}
I want to check, if a a user is in a specific parent OU.
How can I do that?
Check below code for a clear desciption of what I am looking for.
using System.DirectoryServices.AccountManagement;
public bool IsUserInOU(string samAccountName, string OUName){
using (var context = new PrincipalContext(ContextType.Domain))
{
using (var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, samAccountName))
{
//Check if the user is in the OU specified in OUName
//Something like:
//return user.IsInOU(OUName);
}
}
}
public void TestIt_1(){
//The parent OU of this user is "AwesomeOU"
string samAccountName = "Joe";
string OUName = "AwesomeOU";
bool expected = true;
bool actual = IsUserInOU(samAccountName, OUName);
Assert.AreEqual(expected, actual);
}
public void TestIt_2(){
//The parent OU of this user is "WhateverOU"
string samAccountName = "Mike";
string OUName = "AwesomeOU";
bool expected = false;
bool actual = IsUserInOU(samAccountName, OUName);
Assert.AreEqual(expected, actual);
}
The Domain:
National OU
Awesome OU
Joe
Whatever OU
Mike
Solution 1 after empi's answer
With the information given by empi, I wrote the below method to extract the first OU in the DistinguishedName. Having done that, the rest is a breeze.
public static string GetOUForUser(string samAccountName)
{
using (var context = new PrincipalContext(ContextType.Domain))
{
using (var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, samAccountName))
{
//System.Console.WriteLine(user.DistinguishedName);
int startIndex = user.DistinguishedName.IndexOf("OU=", 1) + 3; //+3 for length of "OU="
int endIndex = user.DistinguishedName.IndexOf(",", startIndex);
var group = user.DistinguishedName.Substring((startIndex), (endIndex - startIndex));
return group;
}
}
}
Solution 2 after JPBlanc's answer
public static string GetOUForUser(string samAccountName)
{
using (var context = new PrincipalContext(ContextType.Domain))
{
using (var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, samAccountName))
{
using (DirectoryEntry deUser = user.GetUnderlyingObject() as DirectoryEntry)
{
using (DirectoryEntry deUserContainer = deUser.Parent)
{
return deUserContainer.Properties["Name"].Value.ToString();
}
}
}
}
}
Ok #Empi solution is working, but UserPrincipal is built on DirectoryEntry objects that provides a parent or container properties that just give you the object you are looking for, without using string way.
/* Retreiving a principal context
*/
PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, "WM2008R2ENT:389", "dc=dom,dc=fr", "dom\\jpb", "MyPwd");
/* Retreive a user
*/
UserPrincipal user = UserPrincipal.FindByIdentity(domainContext, "user1");
/* Retreive the container
*/
DirectoryEntry deUser = user.GetUnderlyingObject() as DirectoryEntry;
DirectoryEntry deUserContainer = deUser.Parent;
Console.WriteLine (deUserContainer.Properties["distinguishedName"].Value);
This information is in UserPrincipal.DistinguishedName. You should check if DistinguishedName ends with "," + ou distinguished name (case insensitive). However, you must know the distingushed name of ou you're checking.
For example, if dn is: CN=Jeff Smith,OU=Sales,DC=Fabrikam,DC=COM, then it says that user is in OU=Sales,DC=Fabrikam,DC=COM ou.
This is how I would get the Distinguished Name for a specific AD user, hope it helps :-)
private static string GetDNOfUser(string user)
{
var ctx = new PrincipalContext(ContextType.Domain, Environmentals.Domain, Environmentals.OUPath);
//Creating object for search filter
UserPrincipal userPrin = new UserPrincipal(ctx)
{
//Only getting users with the same name as the input
Name = user
};
var searcher = new PrincipalSearcher
{
//Applying filter to query
QueryFilter = userPrin
};
//Finding the user
var results = searcher.FindOne();
searcher.Dispose();
//Return the distinguishedname
return results.DistinguishedName;
}