online [0 / 0]

  • min
  • max
  • close

user

status

points

logon

Search results

Sign in or register now!


Why not sign up for free and bring this tutorial to bring it to life. Using our Practice-Labs will make this tutorial much easier to follow and provide you with the server to complete the tasks.


What you get with the lab:


  • It's FREE, but if that didn't grab you carry on down the list
  • Access real working Microsoft servers and Cisco networking equipment (dependant on tutorial content)
  • Carry out the tasks outlined in this tutorial without the need for your own equipment
  • Equipment already has the base configurations so you can focus on the parts you need to
  • Make a mistake, no problem in our labs, simply reset the device and start over

More information:


  • Registered users get 60 mins of free lab time for free tutorials
  • Paying users get unlimited lab time in all free tutorials

For unregistered users click hereto register for an account

Already have an account, click hereto login and use a Practice-Lab with this tutorial


Exercise 1 - A brief introduction to C#


Before beginning this exercise take some time to review the Using your Practice-Lab section of the website.

In this exercise you are going to learn how to interact with Microsoft Active Directory using Microsoft Visual C#. Once you have completed the tutorial you will be able to create OUs, create users, search the Active Directory tree for an object and disable accounts.

Most importantly you will learn how to create a c# class and how to add variables and methods to them.

You can find more about learning C# at Microsoft Technet

In this exercise you will be required to Power On and connect to the following servers from your Practice-Lab application:

Domain Controller

Domain Member

If this is the first time you are accessing a Practice-Lab why not take a few minutes to watch our video on getting started, or if you are still having difficulty connecting to your Practice-Lab device please refer to our help pages.

Overview


This tutorial will explain the basics of C# development and how to interact with Microsoft Active Directory Services. This series has been inspired by the growing need for IT Systems Engineers to understand how to automate and interact with services that are used on a day-to-day basis. We hope this tutorial series will help you develop tools that can be used to make your job easier and more efficient.

This tutorial is not meant to be a definitive C# learning guide, but an aide to using C# to assist you in your day-to-day operations.

In this tutorial I will try to avoid such technical terms as

A class is a construct that enables you to create your own custom types by grouping together variables of other types, methods and events. A class is like a blueprint. It defines the data and behaviour of a type. If the class is not declared as static, client code can use it by creating objects or instances which are assigned to a variable.

The professional programmer will need to understand the above statement, but most IT professionals and beginners are not programmers, they are engineers looking after Exchange, Active Directory and Cisco networks, thats where their core skills are, not in programming (I know this, as my core skills are Cisco networking, but I also do some programming). If you have some scripting knowledge this will undoubtedly help you during this tutorial, but you should find this is not a requirement.

This tutorial is aimed solely at the occasional programmer that wants to jump straight in without wanting to know all the technical jargon that goes with it (lets be honest, none of us read the manual anymore right!)

Liability small print

We at Practice-Labs accept no responsibility for any adverse impact to your environment that may be caused by any of the code laid out in this tutorial. We highly recommend that you try out any code that you develop in a test lab and fully understand what your code does before unleashing it on production systems.

C# introduction


Lets jump right in and open up Visual C# Express 2010 that is located on the desktop of the Domain Member server. If you havent done so already, power on both the Domain Controller and the Domain Member servers in the Practice-Lab window in the top right (if this is not displayed click the lab icon beneath the search bar).

If you are not using one of our labs then this will assume you have Visual C# Express 2010 and a TEST domain controller that you can work on (feel free to register to use one of our labs, its free!).

Once you have opened up Visual C# Express, click the new project link and choose Console Application .


Give the project a name (I have called mine ActiveDirectory_User ), and press OK .


Lets briefly explain this layout before we continue.

First we have the toolbox on the left hand side, if we were creating a windows application (a GUI one) then that would contain a bunch of controls that we could drag on to our application (form). In the middle we have our code then on the right we have our project (solution) files and bits and pieces.

The part we are interested in at the moment is the middle section where we are going to place our code.

Within this section there are a number of parts:

1) The using section (namespaces)

2) The namespace declaration

3) The class

4) The main section where our code will be placed

The using section

This is where you can add additional libraries if you like technically these are actually namespaces.

For example if you wanted to interact with SQL server then you would add the System.Data.SQLClient namespace. In a future tutorial well explain more about this.

The main section

You will notice I missed out two sections, thats because at this stage we dont need to understand them.

The main section is where you will put your code, or at least some of it.

Writing our first lines of code


OK now that you have all the basic knowledge you need, its time to write some code.

In this example we are going to interact with Active Directory, specifically users and not computers or anything like that.

To do this we need to include some additional namespaces (libraries) that are not present in the initial console application template. We need to add the following:

System.DirectoryServices

System.DirectoryServices.ActiveDirectory

System.DirectoryServices.AccountManagement

To add these, you put the using keyword in front of the namespace name at the top of your code file as follows:


	using System.DirectoryServices; 
	using System.DirectoryServices.ActiveDirectory; 
	using System.DirectoryServices.AccountManagement;

You will notice that they all go red (red means that there is an error, either syntax or spelling etc)


This is because the C# application doesnt know where to find these, you could liken it to not being in the path, in reality there is no reference to these additional namespaces so we need to add a reference to them. To do this, on the right hand side where you see References right click the References folder and choose Add reference


A new dialogue will appear


Click the .Net tab and locate System.DirectoryServices then press OK .


You will find that we are still missing a reference, so go ahead and add a reference to System.DirectoryServices.AccountManagment.

You should now have no red errors in the using section of the code:


Summary


In this exercise you create a new console application and added references to some additional namespaces that will enable you to interact with Active Directory. Continue to exercise 2 to start coding!


Exercise 2 - Creating your first Class


In this exercise you are going to create your first class. This class will define a User which will have a number of variables and methods (thats functions) to achieve certain things.

In this exercise you will be required to Power On and connect to the following servers from your Practice-Lab application:

Domain Controller

Domain Member

If this is the first time you are accessing a Practice-Lab why not take a few minutes to watch our video on getting started, or if you are still having difficulty connecting to your Practice-Lab device please refer to our help pages.

A class is defined by Microsoft as:

A class is a construct that enables you to create your own custom types by grouping together variables of other types, methods and events. A class is like a blueprint. It defines the data and behaviour of a type. If the class is not declared as static, client code can use it by creating objects or instances which are assigned to a variable.

For ease of understand I am going to define a class as a piece of code that defines an object that we can assign variables and functions to (plus events, but thats a bit advanced for us).

This Class will be an Active Directory user, i.e. we are going to create a user object. The user object needs to have some properties that we can assign values to ( variables ). These variables will be of different Types depending on what it will store, for example we want a string Type as Firstname, it cant be a Boolean type (on/off, true/false), or an integer number (a whole number) it needs to be a string.

We also want to store something like Account Disabled , now this is either on or off (true or false) so a Boolean is a great storage Type for this variable. A list of the variable names and types are as follows:

  • String : Firstname
  • String : Lastname
  • String : LoginId
  • String : Office
  • String : EmailAddress
  • Bool : IsDisabled

To create our Class we need to declare it, place your cursor below the class program statement and above the static void main statement and type the following:


	public class User 
	{

	}
    

Your code should look like:


	namespace ActiveDirectory_User 
	{ 
  class Program 
  {
   public class User 
   { 
   }

   static void Main(string[] args) 
   { 
   } 
  }
    }

The public statement means that its going to be accessible to other areas of our program (accessibility is a long topic that were not going to worry about for now).

Next lets give this user class some variables:


public class User 
{ 
  public string Firstname; 
  public string Lastname; 
  public string LoginId; 
  public string Office; 
  public string EmailAddress; 
  public bool IsDisabled; 
}

Before we continue, you can see the affect that these lines of code have had by placing your cursor in main application section (static void main) and start to type the word User . You will notice intellisense picks up our user class!


Normally to instantiate (create) an instance of our User class (that means create a new User), we would type something like:


	User MyNewUser = new User();

However, sometimes when you create a new object you create it and pass some parameters to it, for example:


static void Main(string[] args) 
{ 
  // New user object with no settings passed 
  User MyNewUser = new User();

  // New user object with first and surnames passed 
  User FredBlogs = new User("Fred", "Blogs"); 
}

How do they achieve that?

Well lets go back to our User class, we simply add a new way to create the object, this can be done as follows:

Note : Notice we simply drop the word class to achieve a new object creation method (this is called a constructor)


public class User 
{ 
  public string Firstname; 
  public string Lastname; 
  public string LoginId; 
  public string Office; 
  public string EmailAddress; 
  public bool IsDisabled;

  public User(string firstName, string lastName) 
  { 
   Firstname = firstName; 
   Lastname = lastName; 
  } 
}

We can now create a new user by passing their first and surname to the construction of the object which in turn will automatically set the first and surnames.

You will notice that by adding these lines, we now have an error on our first user statement:


This is because there is now no parameter-less way of creating our User object. To fix this, we can either not allow a parameter-less construction of the object OR we can add in a parameter-less way to make a new User object:


	public User() { }

Our class now looks like this:


public class User 
{ 
  public string Firstname; 
  public string Lastname; 
  public string LoginId; 
  public string Office; 
  public string EmailAddress; 
  public bool IsDisabled;

  public User() { }

  public User(string firstName, string lastName) 
  { 
   Firstname = firstName; 
   Lastname = lastName; 
  } 
}

And you will notice our error has gone:


You can have as many construction types as you want, you can even include optional parameters and set the default if the parameter is not passed, for example you could do:


public User(string firstName, string lastName, string office = "London",) 
{ 
 Firstname = firstName; 
 Lastname = lastName; 
 Office = office; 
}

This would set the office to London if the office was not specified.

One thing to note is the use of variable names. You will notice that (my preference) is to use camelCase (thats the first letter is always lower in a set of words) for variables I am passing IN to a function, and PascalCase for pretty much everything else. This is my way, its not best practice, but what I do recommend is you standardise the way in which you create your methods, functions and variables so that they are consistent.

There are many resources out there on the internet for you to find how best practice c# programming should be done!

Summary


In this exercise you created a class and added a constructor to that class now you can create a new instance of the class by either by passing in the users first and last names, or by passing nothing. If you pass nothing, then you should understand the different default values to your variables, for instance a Boolean by default is false therefore IsDisabled on our User object would be set to disabled.


Exercise 3 - Connecting to Active Directory and Creating an OU


In this exercise we are going to make a connection to Active Directory and create some new Organisational Units ready for us to place some users in. You will also use your first loop mechanism to create these organisational units (feel free to rename and add to these to make them more relevant to you).

You will also learn about try-catch blocks and use these to handle errors that may occur during any of the processing that takes place.

In this exercise you will be required to Power On and connect to the following servers from your Practice-Lab application:

Domain Controller

Domain Member

If this is the first time you are accessing a Practice-Lab why not take a few minutes to watch our video on getting started, or if you are still having difficulty connecting to your Practice-Lab device please refer to our help pages.

Connecting to Active Directory


Before we make use of our new User class we are going to create a few organisational units. To do this, we need to some information about the Active Directory server so that we can connect to it.

Here is the Active Directory information that is valid in our lab that we need to build our connection string (if you are not using a lab then you will need to change some of the settings in the code below):

  • Domain name: PRACTICELABS
  • Domain Controller: PLABDC01
  • User name: Administrator
  • Password: Passw0rd

Note: In real life you wouldnt be using the Administrator account to do these tasks!

To create the function that will create an OU move your cursor to below the static void main block and type the following:


public static void CreateOU(string ou) 
{ 
 try 
 { 
  if (!DirectoryEntry.Exists("LDAP://PLABDC01/ou=" + ou + ",dc=PRACTICELABS,dc=COM")) 
   { 
    try 
    { 
     DirectoryEntry ActiveDirectory = new DirectoryEntry("LDAP://PLABDC01/dc=PRACTICELABS,dc=COM", "Administrator", "Passw0rd"); 
     DirectoryEntry NewOU = ActiveDirectory.Children.Add("OU=" + ou, "OrganizationalUnit"); 
     NewOU.CommitChanges(); 
     ActiveDirectory.CommitChanges(); 
     Console.WriteLine("Created OU:{0}", ou); 
    } 
    catch (Exception error) 
    { 
     Console.WriteLine("An error occured while creating group:{0} :\n{1}", ou, error.Message); 
    } 
   } 
   else 
   { 
    Console.WriteLine("OU already exists"); 
   } 
  } 
  catch (Exception error) 
  { 
   Console.WriteLine("We couldnt connect to AD! Is the server powered on?. Exception generated was\n{0}", error.Message); 
  } 
}

Lets go through these lines one by one:


	public static void CreateOU(string ou)

This line declares the function, we return nothing to the caller ( void ), its static meaning we dont have to generate a new instance of a class to use it (dont worry too much about this), the function name is CreateOU and finally, when we call the function we need to pass it the OU name (as a string) that we are going to create.


try 
{
}
catch (Exception error) 
{
}

These lines within the code catch any exceptions (errors/crashes if you like) that could occur. Its a really good idea to use these wherever you feel that an error could occur. A typical example is when you are dealing with external processes such as connecting to Active Directory, SQL Server, Exchange Server or just reading a plain text file that might not exist.

Code that is present within the try block will execute until a failure occurs, if one occurs then the exception message is passed to the catch block giving you the opportunity to do anything you need to do when an error occurs. You can have the optional finally {} block too which will execute whether a crash occurs or not, this is a great way to clean up (we are not covering dispose() or using() in this tutorial, but you can use dispose to help free up resources). If you added a finally statement, it would look like this:


try 
{
}
catch (Exception error) 
{
}
finally
{
}

if (!DirectoryEntry.Exists("LDAP://PLABDC01/ou=" + ou + ",dc=PRACTICELABS,dc=COM"))

This line attempts to connect to Active Directory and determine if our OU exists (please note that we are only checking in the root of the tree!). If the OU does NOT exist the exclamation mark ! means not i.e:


if(1 != 2)
{
 //this is true;
}

DirectoryEntry Directory = new DirectoryEntry("LDAP://PLABDC01/dc=PRACTICELABS,dc=COM", "Administrator", "Passw0rd"); 
DirectoryEntry NewOU = Directory.Children.Add("OU=" + ou, "OrganizationalUnit"); 
NewOU.CommitChanges(); 
Directory.CommitChanges(); 
Console.WriteLine("Created OU:{0}", ou);

Thee 5 lines of code (they may appear wrapped) achieve the following:

Create a new connection to Active Directory, setting the context to the root (PRACTICELABS.COM), and specifying a username and password to connect with.

Create a new directory Organisational Unit object.

Commit the changes to the NewOU.

Commit the changes to Directory.

The last statement I will explain is this one:


Console.WriteLine("An error occured while creating group:{0} :\n{1}", ou, error.Message);

This statement writes an error message to the console, however the reason I wanted to explain it is because of the use of the \n and {0} commands. A \n is a carriage return, and the curly braces specifies that we are going to insert the values at the end of the command. You will see , ou followed by , error.Message . This means {0} will be populated with the value of ou which we originally passed in to the function, and {1} will be on a new line and populated with the value of error.Message (you could also display the contents of error.InnerException too which may help diagnosing issues).

Creating the OUs

OK So we have our OU creation code. So now we need to call it.

Finally we will add some meaningful code in the static void main section of our project where the entry point in to the program is (i.e. when I press run, the code inside this block will execute).


string[] Departments = { "Marketing", "Sales", "Human Resources" }; 
foreach (string dept in Departments) 
{ 
 CreateOU(dept); 
}

This block of code does the following:


string[] Departments = { "Marketing", "Sales", "Human Resources" }; //Creates a string Array with the specified values. 
foreach (string dept in Departments) 
{ 
 CreateOU(dept); 
}

These commands iterate (loop) over each value in our string array passing in a variable called dept . We then call the CreateOU function and pass it the value of dept . Basically CreateOU is called with each of the values in our Department array.

We could have easily done:


CreateOU("Marketing"); 
CreateOU("Sales"); 
CreateOU("Human Resources");

But I wanted to show you a string array and an iteration statement using foreach.

This will create our OUs in sequence, to verify if you run the application now (press the green play button in the toolbar at the top of the Visual C# Express application). After it runs, connect to the Active Directory server, then open Active Directory Users and Computers, you should see your new OUs!


Before:


After:


Summary


In this exercise you created your first function which took a parameter that created an Organisational Unit in Active Directory. You used a string[] array to iterate through to pass the value of the array through to the OU create function.


Exercise 4 - Creating our Active Directory Users


In this exercise we are finally going to create our Active Directory users.

In this exercise you will be required to Power On and connect to the following servers from your Practice-Lab application:

Domain Controller

Domain Member

If this is the first time you are accessing a Practice-Lab why not take a few minutes to watch our video on getting started, or if you are still having difficulty connecting to your Practice-Lab device please refer to our help pages.

Creating an Active Directory user using C#


To create a user we are going to create a method on our User class. A method is basically a function that you can call on the object itself. They key point here is that you have access to all the variables on that object when you call the function, i.e. the User object is in context if you like.

This may not be the best approach to creating our user, however it covers a key topic for classes which are methods.

In your user class code section, add the following code:


public bool CreateAccount() 
{ 
 // wrap our connection in a try catch block which will safeguard us against application crash if for example we can't connect to AD 
 try 
 { 
  string FullPath = "LDAP://PLABDC01/ou=" + Department + ",dc=PRACTICELABS,dc=COM"; 

  // Active directory connection 
  DirectoryEntry Directory = new DirectoryEntry(FullPath, "Administrator", "Passw0rd");

  // New user 
  DirectoryEntry NewUser = Directory.Children.Add("CN=" + LoginId, "user"); 

  // givenName is first name  
  NewUser.Properties["givenName"].Value = Firstname;

  // sn is last name 
  NewUser.Properties["sn"].Value = Lastname;

  // login id 
  NewUser.Properties["sAMAccountName"].Value = LoginId;

  // office 
  NewUser.Properties["physicalDeliveryOfficeName"].Value = Office; 

  // commit the new user 
  NewUser.CommitChanges();

  // update the user to be enabled, here we CAST the value as an integer (i.e. we instruct the compiler that the return type value will be an int.  

  // casting this will cause exceptions if the return type is not what you specify so beware! 
  int val = (int)NewUser.Properties["userAccountControl"].Value; 
  NewUser.Properties["userAccountControl"].Value = val & ~0x2; 
  NewUser.CommitChanges(); 

  // everything worked ok, return a value of true 
  return true; 
 } 
 catch (Exception error) 
 { 
  // an error occured, write the error message out and return a value of false 
  Console.Write("An error occured while creating user:{0} {1}: \n{2}", Firstname, Lastname, error.Message); 
  return false; 
  } 
 }

The following describes this block of code:

First we declare our method called CreateAccount(), this returns a value of true or false ( bool ), true if creating the account succeeded and false if it fails.

The code itself is wrapped in a try catch block, if execution reaches the catch then it will return false as something went wrong and display an error on the console to us so we can help diagnose the problem.

The guts of the code works in a similar way to the Organisational unit creation code:

First we create an Directory object that connects to AD, we then create another Directory object (NewUser) assign it some values and commit the changes. Note how the attributes of the user are set!

This time we then set the changes, modify the object and re-commit the changes, this is because we need to enable the account after we have created it as by default the account will be disabled.

One other key point to this code is where are the values coming from, for example, the login id and department name? Well these values are already bound to the user object itself as the object is in context to the code being executed. All the variables of the User object can be accessed at this point, we could even make some private variables that are only accessible to Methods on the object and not available to the outside code.

Hopefully you can follow it through line by line, if not, at the end of this tutorial is an annotated version of the full code listing.

Calling the user create AD account code


To call this code, we are going to create a new function that will generate a list of random User objects. Once the object has been created we are going to call the CreateAccount() method.

Add the following section of code to your program, under the static void main block:



public static List<User> GenerateRandomUserAccounts() 
{ 
 List<User> RandomUsers = new List<User>();// create an empty list of users

 string[] Firstnames = { "Bart", "Homer", "Maggie", "Marge", "Lisa", "Ned" }; // our firstnames 
 string[] Lastnames = { "Simpson", "Flanders", "Smith" }; // our lastnames 
 string[] Departments = { "Marketing", "Sales", "Human Resources" }; // our OUs 
 string[] Offices = { "London", "New York", "Hong Kong", "Japan" }; // our offices

 Random RandomNumber = new Random(); // a new random generator

 foreach (string l in Lastnames)// loop through surnames 
 { 
  foreach (string f in Firstnames)//loop through firstnames 
  { 
   int DepartmentId = RandomNumber.Next(0, Departments.Length); // get a random department (using the position index) 
   int OfficeId = RandomNumber.Next(0, Offices.Length); 
   User NewUser = new User(f, l, f + "." + l, Departments[DepartmentId], Offices[OfficeId], f + "." + l + "@practicelabs.com"); // create a new user with the f(first), l(last), login (first.last), department, office and email 
   RandomUsers.Add(NewUser); // add this user to our list 
   if (NewUser.CreateAccount()) // create the account 
   { 
    Console.WriteLine("Created user OK:" + f + " " + l); 
   } 
  } 
  } 
 return RandomUsers; // return our list 
}

First we declare a new variable that will store our created random user. This is a List of our User class.

Next we define a number of string arrays containing first and last names, departments and offices.

We then create a new random number generator and loop through all the last names and inside this block iterate through all the first names, which basically gives us a total of 18 user accounts (6 to the power 3).

While we iterate through the user first and last names, we chose at random a department and office location. We use the random.next(x,y) command which creates a random number between x and y. In this case we are choosing zero (as all our arrays are zero based) and the length of the array.

Finally we call NewUser.CreateAccount() albeit its in an if statement! How does that work, well the if statement actually executes the command, its able to do this as the return from the CreateAccount method is a bool right!

If the account is created then we write some information to the console.

Calling our Generate Random User code


To call our random user creation code we need to kick the process off from our main program entry point.

So within our static void main block we can execute this block of code by doing the following:


List<User> MyRandomUsers = GenerateRandomUserAccounts();

Remember that our GenerateRandomUserAccounts code passes back the list of created accounts which means we can use this in our Main block. We store this in a local variable in the Main block called MyRandomUsers.

Just to prove it we can iterate over the users:


foreach (User u in MyRandomUsers) 
{ 
 Console.WriteLine((u.Firstname + " " + u.Lastname).PadRight(18, ' ') + u.Department.PadRight(18, ' ') + u.Office); 
}

Now login go the Domain Controller server and open the Active Directory Users and computers program and navigate through the domain tree to find all the new accounts your code created!

Note: You will get an OU already exists message as we created those before!


Our new users (yours will vary)


Summary


In this exercise you created a function to create some random user accounts, pass them back to the main code section of the program and write each user to the console. You learnt how to attach a method to a class and hopefully you can see how useful this could be!


Exercise 5 - Bonus material disabling a user


This exercise is an added method that you can attach to your user class, this method will disable the user in context that the method is called on. The reason for adding this method is twofold. Firstly disabling users is quite useful, but primarily because we are going to use an Active Directory search facility to locate the user in Active Directory to then disable.

The code for disabling the user method is as follows:


public bool DisableAccount() 
{ 
 try 
 { 
  DirectoryEntry Directory = new DirectoryEntry("LDAP://dc=PRACTICELABS,dc=COM"); 
  DirectorySearcher SearchAD = new DirectorySearcher(Directory); 
  SearchAD.Filter = "(SAMAccountName=" + LoginId + ")"; 
  SearchAD.CacheResults = false; 
  SearchResult result = SearchAD.FindOne(); 
  Directory = result.GetDirectoryEntry(); 
  Directory.Properties["userAccountControl"].Value = 0x0002; 
  Directory.CommitChanges(); 
  return true; 
 } 
 catch (Exception error) 
 { 
  Console.WriteLine("An error occured when disabling this user:{0}\n{1}", LoginId, error.Message); 
  return false; 
 } 
}

To call the code, we can do something like this:


int Count = 0; 
foreach (User u in MyRandomUsers) 
{ 
 if (Count % 2 == 0) 
 { 
  if (u.DisableAccount()) 
  { 
   Console.WriteLine("Disabled: {0}  {1} in department: {2}", u.Firstname, u.Lastname, u.Department); 
  } 
  else 
  { 
   Console.WriteLine("Failed to disable: {0}  {1} in department: {2}", u.Firstname, u.Lastname, u.Department); 
  } 
 } 
 Count++; 
}

This small block of code, placed below our call of the generate users code (so that we have our list of generated users) iterates through each user then makes a mathematical calculation which is if our counter (Count) is divisible by 2 then we disable the account. In other words, we disable half of our users!

Summary


In this final part of the tutorial we added a new method that disabled our account. Hopefully you can see the unlimited possibilities of classes and c# as a programming language. Whilst there are many improvements that could be made to all areas of the code written in this tutorial, hopefully it will give you enough information and inspiration to experiment and try new things and give you new ways to achieve tasks.


Exercise 6 - Code review


The following outlines the entire code module, if you are pasting this in to your own project, dont forget to add the references explained in exercise 1!


using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.DirectoryServices; 
using System.DirectoryServices.ActiveDirectory; 
using System.DirectoryServices.AccountManagement;

namespace ActiveDirectory_User 
 {
  class Program 
  { 
  // our User class 
  public class User 
  { 
   // our user variables 
   public string Firstname; 
   public string Lastname; 
   public string LoginId; 
   public string Department; 
   public string Office; 
   public string EmailAddress; 
   public bool IsDisabled;

   // Default constructor for our user object 
   public User() { }

   // Custom constructor that takes a set of parameters and sets the respective variable - notice how I change 
   // the variable from camelCase to PascalCase - this is how I program, you do not have to do this but do get in to a 
   // habit of standardising your code variables 
   public User(string firstName, string lastName, string loginId, string department, string office, string emailAddress) 
   { 
    Firstname = firstName; 
    Lastname = lastName; 
    LoginId = loginId; 
    Department = department; 
    Office = office; 
    EmailAddress = emailAddress; 
   }

   // user method one (CreateAccount) 
   public bool CreateAccount() 
   { 
    // wrap our connection in a try catch block which will safeguard us against application crash if for example we can't connect to AD 
    try 
    { 
     string FullPath = "LDAP://PLABDC01/ou=" + Department + ",dc=PRACTICELABS,dc=COM";

     // Active directory connection 
     DirectoryEntry Directory = new DirectoryEntry(FullPath, "Administrator", "Passw0rd");

     // New user 
     DirectoryEntry NewUser = Directory.Children.Add("CN=" + LoginId, "user"); 

     // givenName is first name  
     NewUser.Properties["givenName"].Value = Firstname;

     // sn is last name 
     NewUser.Properties["sn"].Value = Lastname;

     // login id 
     NewUser.Properties["sAMAccountName"].Value = LoginId;

     // office 
     NewUser.Properties["physicalDeliveryOfficeName"].Value = Office; 

     // commit the new user 
     NewUser.CommitChanges();

     // update the user to be enabled, here we CAST the value as an integer (i.e. we instruct the compiler that the return type value will be an int.  
     // casting this will cause exceptions if the return type is not what you specify so beware! 
     int val = (int)NewUser.Properties["userAccountControl"].Value; 
     NewUser.Properties["userAccountControl"].Value = val & ~0x2; 
     NewUser.CommitChanges(); 

     // everything worked ok, return a value of true 
     return true; 
    } 
    catch (Exception error) 
    {
     // an error occured, write the error message out and return a value of false 
     Console.Write("An error occured while creating user:{0} {1}: \n{2}", Firstname, Lastname, error.Message); 
     return false; 
    } 
   }

   // user method that searches active directory to find our account and then disable it 
   public bool DisableAccount() 
   { 
    // wrap our method in a try catch block in case it fails when we connect to AD or something 
    try 
    { 
     // attach to AD 
     DirectoryEntry Directory = new DirectoryEntry("LDAP://dc=PRACTICELABS,dc=COM"); 

     // create an AD search object 
     DirectorySearcher SearchAD = new DirectorySearcher(Directory); 

     // add our filter which is our login id 
     SearchAD.Filter = "(SAMAccountName=" + LoginId + ")"; 
     SearchAD.CacheResults = false;

     // get the result 
     SearchResult Result = SearchAD.FindOne(); 
     Directory = Result.GetDirectoryEntry();

     // if we get the result, disable the account and commit the changes 
     Directory.Properties["userAccountControl"].Value = 0x0002; 
     Directory.CommitChanges(); 
     return true; 
    } 
    catch (Exception error) 
    { 
     // oh dear something went wrong, again write the error message out including the login id 
     Console.WriteLine("An error occured when disabling this user:{0}\n{1}", LoginId, error.Message); 
     return false; 
    } 
   }
  }

  static void Main(string[] args) 
  { 
   // create our OU's 
   string[] Departments = { "Marketing", "Sales", "Human Resources" }; 
   foreach (string dept in Departments) 
   { 
    CreateOU(dept); 
   } 

   // generate our random users - this populates AD 
   List<User> MyRandomUsers = GenerateRandomUserAccounts();

   // write our user information to the console so we can see the users that were created 
   foreach (User u in MyRandomUsers) 
   { 
    Console.WriteLine((u.Firstname + " " + u.Lastname).PadRight(18, ' ') + u.Department.PadRight(18, ' ') + u.Office); 
   }

   // disable every other account 
   int Count = 0; 
   foreach (User u in MyRandomUsers) 
   { 
    if (Count % 2 == 0) 
    { 
     if (u.DisableAccount()) 
     { 
      Console.WriteLine("Disabled: {0}  {1} in department: {2}", u.Firstname, u.Lastname, u.Department); 
     } 
     else 
     { 
      Console.WriteLine("Failed to disable: {0}  {1} in department: {2}", u.Firstname, u.Lastname, u.Department); 
     } 
    } 
    Count++; 
   }

   // this is an added function not explained in the tutorial, for more information see the explaination of the code beloew 
   UpdateDisabled(MyRandomUsers);

   // write out the users (proves the update of the IsDisabled flag of the user object 
   foreach (User u in MyRandomUsers) 
   { 
    if (u.IsDisabled) 
    { 
     Console.WriteLine("Account:{0} is disabled", u.LoginId); 
    } 
   }

   // wait for a keypress so everything doesnt disapear 
   Console.ReadLine(); 
  }

  public static void UpdateDisabled(List<User> users) 
  { 
   Console.WriteLine("Updating disabled accounts"); 
   foreach (User u in users) 
   { 
    try 
    { 
     DirectoryEntry Directory = new DirectoryEntry("LDAP://dc=PRACTICELABS,dc=COM"); 

     DirectorySearcher Search = new DirectorySearcher(Directory); 
     Search.Filter = "(SAMAccountName=" + u.LoginId + ")"; 
     Search.CacheResults = false; 
     SearchResult Result = Search.FindOne(); 

     Directory = Result.GetDirectoryEntry(); 
     object o = Directory.Properties["userAccountControl"].Value; 

     // (514 = disabled) 
     if ((int)Directory.Properties["userAccountControl"].Value == 514) 
     { 
      // this account is disabled 
      u.IsDisabled = true; 
     } 
     else 
     { 
      // this account is not disabled 
      u.IsDisabled = false; 
     } 
    } 
    catch (Exception error) 
    { 
     Console.WriteLine("An error occured when disabling this user:{0}\n{1}", u.LoginId, error.Message); 
    } 
   } 
  }

  public static void CreateOU(string ou) 
  { 
  try 
  { 
   if (!DirectoryEntry.Exists("LDAP://PLABDC01/ou=" + ou + ",dc=PRACTICELABS,dc=COM")) 
   { 
    try 
    { 
     DirectoryEntry ActiveDirectory = new DirectoryEntry("LDAP://PLABDC01/dc=PRACTICELABS,dc=COM", "Administrator", "Passw0rd"); 
     DirectoryEntry NewOU = ActiveDirectory.Children.Add("OU=" + ou, "OrganizationalUnit"); 
     NewOU.CommitChanges(); 
     ActiveDirectory.CommitChanges(); 
     Console.WriteLine("Created OU:{0}", ou); 
     } 
    catch (Exception error) 
    { 
     Console.WriteLine("An error occured while creating group:{0} :\n{1}", ou, error.Message); 
    } 
   } 
   else 
   { 
    Console.WriteLine("OU already exists"); 
   } 
  } 
  catch (Exception error) 
  { 
   Console.WriteLine("We couldnt connect to AD! Is the server powered on?. Exception generated was\n{0}", error.Message); 
  } 
 }

 public static List<User> GenerateRandomUserAccounts() 
 { 
  List<User> RandomUsers = new List<User>();
  string[] Firstnames = { "Bart", "Homer", "Maggie", "Marge", "Lisa", "Ned" }; // our firstname 
  string[] Lastnames = { "Simpson", "Flanders", "Smith" }; // our lastname 
  string[] Departments = { "Marketing", "Sales", "Human Resources" }; // our OU 
  string[] Offices = { "London", "New York", "Hong Kong", "Japan" }; // our office

  Random RandomNumber = new Random();

  foreach (string l in Lastnames) 
  { 
   foreach (string f in Firstnames) 
   { 
    int DepartmentId = RandomNumber.Next(0, Departments.Length); 
    int OfficeId = RandomNumber.Next(0, Offices.Length); 
    User NewUser = new User(f, l, f + "." + l, Departments[DepartmentId], Offices[OfficeId], f + "." + l + "@practicelabs.com"); 
    RandomUsers.Add(NewUser); 
    if (NewUser.CreateAccount()) 
    { 
     Console.WriteLine("Created user OK:" + f + " " + l); 
    } 
   } 
  } 
  return RandomUsers; 
 } 
 }
}