This application is designed to query an active directory, and at the moment, performs only two tasks:
- Save a list of all users to a file.
- Save a list of all groups that all users are in to a file.
I tried to implement a print all groups method, but ended up removing it. I believe I removed all references to it from this code, but if you see one, please ignore (or fuss at me for not scrutinizing enough).
The method that saves all user groups uses a background worker due to how much longer it takes to run. I understand I should probably add a background worker for the save users method too.
Users are able to change both the domain and the organizational units using text boxes.
ActiveDirectoryTool.cs:
public partial class ActiveDirectoryTool : Form
{
private Backend backend;
public ActiveDirectoryTool()
{
InitializeComponent();
backend = new Backend();
UpdateDisplay();
}
private void getAllUsers_Click(object sender, EventArgs e)
{
this.Enabled = false;
if (backend.PrintAllUsersToFile())
{
this.Enabled = true;
}
}
private void printAllUserGroups_Click(object sender, EventArgs e)
{
if (!backgroundWorker1.IsBusy)
{
this.Enabled = false;
backgroundWorker1.RunWorkerAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
backend.PrintAllUserGroupsToFile();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.Enabled = true;
}
private void UpdateBackend()
{
backend.Domain = domainBox.Text;
backend.OrganizationalUnits = organizationalUnitBox.Text;
backend.WriteSettings();
}
private void UpdateDisplay()
{
domainBox.Text = backend.Domain;
organizationalUnitBox.Text = backend.OrganizationalUnits;
scopeDisplay.Text = backend.Scope;
}
private void organizationalUnitBox_TextChanged(object sender, EventArgs e)
{
UpdateBackend();
UpdateDisplay();
}
private void domainBox_TextChanged(object sender, EventArgs e)
{
UpdateBackend();
UpdateDisplay();
}
}
Backend.cs:
internal class Backend
{
private const string DefaultDomain = "dnet.domtar";
private const string CommaSeparatedValuesExtension = ".csv";
private const string PlainTextExtension = ".txt";
private const string TabSeparatedValuesExtension = ".tsv";
private const string DefaultExtension = PlainTextExtension;
private const string DateTimeFormat = "yyyyMMddTHHmmss";
private const char Hyphen = '-';
private const char Tab = '\t';
private const char Comma = ',';
private const string UserListHeader = "Last\tFirst\tDisplay Name\tID\tActive\tLocked\tDescription\tHome Drive\tHome Folder\tLogin Script\tEmail\tStreet\tCity\tState\tPhone\tDistinguished Name";
private const string GroupListHeader = "Group Name\tGroup ID\tManaged By\tDescription\tDistinguished Name";
private const string UserGroupListHeader = "User ID\tGroup\tUser Full Name\tUser Distinguished Name";
private string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "ActiveDirectoryTool");
public Backend()
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
ReadSettings();
}
private string domain;
private string domainContext;
private string organizationalUnits;
public string Domain
{
get
{
return domain;
}
set
{
domain = value;
}
}
public string OrganizationalUnits
{
get
{
return organizationalUnits.Replace("OU=", "").Replace(",", " ");
}
set
{
organizationalUnits = "OU=" + value.Replace(" ", ",OU=");
}
}
private DirectoryEntry DefaultRootDirectory
{
get
{
return new DirectoryEntry("LDAP://RootDSE");
}
}
private DirectoryEntry RootDirectory
{
get
{
if (!String.IsNullOrWhiteSpace(Domain) && !Domain.Equals(DefaultDomain))
{
return new DirectoryEntry("LDAP:://" + Domain);
}
else
{
return DefaultRootDirectory;
}
}
}
public string DomainContext
{
get
{
if (String.IsNullOrWhiteSpace(domainContext))
{
domainContext = GetDefaultDomainContext();
}
return domainContext;
}
}
public string Scope
{
get
{
return organizationalUnits + Comma + DomainContext;
}
}
private string GetDefaultDomainContext()
{
return RootDirectory.Properties["defaultNamingContext"].Value as string;
}
private PrincipalContext GetPrincipalContext()
{
return new PrincipalContext(ContextType.Domain, Domain, Scope);
}
public void WriteSettings()
{
ConfigurationManager.AppSettings["domain"] = domain;
ConfigurationManager.AppSettings["organizationalUnits"] = organizationalUnits;
}
private void ReadSettings()
{
domain = ConfigurationManager.AppSettings["domain"];
organizationalUnits = ConfigurationManager.AppSettings["organizationalUnits"];
}
private void ShowException(Exception e)
{
MessageBox.Show("Exception: " + e.Message + "\n" + e.StackTrace);
}
private string GenerateFilename(string fileType)
{
return fileType + Hyphen + DateTime.Now.ToString(DateTimeFormat) + DefaultExtension;
}
private bool IsActive(DirectoryEntry de)
{
if (de.NativeGuid == null) return false;
int flags = (int)de.Properties["userAccountControl"].Value;
return !Convert.ToBoolean(flags & 0x0002);
}
private string ConcatenateWithTabs(params string[] strings)
{
string concatenated = "";
foreach (string s in strings)
{
concatenated += s + Tab;
}
return concatenated;
}
private string UserAsString(UserPrincipal user)
{
DirectoryEntry entry = user.GetUnderlyingObject() as DirectoryEntry;
return ConcatenateWithTabs(
user.Surname,
user.GivenName,
user.DisplayName,
user.SamAccountName,
IsActive(entry).ToString(),
user.IsAccountLockedOut().ToString(),
user.Description,
user.HomeDrive,
user.HomeDirectory,
user.ScriptPath,
user.EmailAddress,
(string)entry.Properties["streetAddress"].Value,
(string)entry.Properties["l"].Value,
(string)entry.Properties["st"].Value,
user.VoiceTelephoneNumber,
user.DistinguishedName);
}
private string UserGroupAsString(UserPrincipal user, GroupPrincipal group)
{
return ConcatenateWithTabs(
user.SamAccountName,
group.SamAccountName,
user.Name,
user.DistinguishedName);
}
public bool PrintAllUsersToFile()
{
try
{
int count = 0;
string filename = Path.Combine(path, GenerateFilename("AllUsers"));
using (var searcher = new PrincipalSearcher(new UserPrincipal(GetPrincipalContext())))
{
using (StreamWriter sr = new StreamWriter(filename))
{
sr.WriteLine(UserListHeader);
foreach (var result in searcher.FindAll())
{
sr.WriteLine(UserAsString((UserPrincipal)result));
count++;
}
}
}
MessageBox.Show("All (" + count + ") users saved to file " + filename);
}
catch (Exception e)
{
ShowException(e);
}
return true;
}
public bool PrintAllUserGroupsToFile()
{
try
{
int count = 0;
string filename = Path.Combine(path, GenerateFilename("UserGroups"));
using (var searcher = new PrincipalSearcher(new UserPrincipal(GetPrincipalContext())))
{
using (StreamWriter sr = new StreamWriter(filename))
{
sr.WriteLine(UserGroupListHeader);
foreach (UserPrincipal user in searcher.FindAll())
{
foreach (GroupPrincipal group in user.GetGroups())
{
sr.WriteLine(UserGroupAsString(user, group));
}
count++;
}
}
}
MessageBox.Show("All (" + count + ") users with groups saved to file " + filename);
}
catch (Exception e)
{
ShowException(e);
}
return true;
}
}