Creating Objects in Active Directory


The most fundamental object in Active Directory is the OU. One of the most frustrating problems for new network administrators is that by default, when Active Directory is installed, all users are put in the users container, and all computers are put in the computers container- and of course you can not apply Group Policy to a container.

Creating an Organizational Unit

The process of creating an OU in Active Directory will provide the basis for creating other objects in Active Directory because the technique is basically the same. The key to effectively using PowerShell to create objects in Active Directory is using the Active Directory Service Interfaces (ADSI) accelerator.

Just the Steps 

To create an object by using ADSI

  1. Use the [ADSI] accelerator

  2. Use the appropriate ADSI provider

  3. Specify the path to the appropriate object in Active Directory

  4. Use the SetInfo() method to write the changes

The image from book CreateOU.ps1 script shown here illustrates each of the steps required to create an object by using ADSI. The variable $strClass is used to hold the class of object to create in Active Directory. For this script, we will be creating an OU. We could just as easily create a user, or a computer-as we will see shortly. We use the variable $strOUName to hold the name of the OU we are going to create. For the image from book CreateOU.PS1 script, we are going to create an OU called MyTestOU. Because we will pass this variable directly to the Create command, it is important we use the form shown here:

 $strOUName="ou=MyTestOU"

The attribute that is used to create an object in Active Directory is called the relative distinguished name (RDN). Standard attribute types are expected by ADSI-such as “ou” for organizational unit. We will look at RDNs in the section on Lightweight Directory Access Protocol (LDAP) names in this chapter. The next line of code in the image from book CreateOU.PS1 script makes the actual connection into Active Directory. To do this, we use the [ADSI] accelerator. The [ADSI] accelerator wants to be given the exact path to your connection point in Active Directory (or some other directory, as we will see shortly) and the name of the ADSI provider. The target of the ADSI operation is called the ADsPath.

In the image from book CreateOU.PS1 script, we are connecting to the root of the NwTraders.msft domain, and we are using the LDAP provider. The other providers we can use with ADSI are shown in Table 7-1. After we make our connection into Active Directory, we hold the system. DirectoryServices.DirectoryEntry object in the $objADSI variable.

Table 7-1: ADSI-Supported Providers
Open table as spreadsheet

Provider

Purpose

WinNT

To communicate with Windows NT 4.0 Primary Domain Controllers (PDCs) and Backup Domain Controllers (BDCs), and with local account databases for Windows 2000 and newer workstations and servers

LDAP

To communicate with LDAP servers, including an Exchange 5.x directory and Windows 2000 Server or Windows Server 2003 Active Directory

NDS

To communicate with Novell Directory Services servers

NWCOMPAT

To communicate with Novell NetWare 3.x servers

Armed with the connection into Active Directory, we can now use the create method to create our new object. The system.DirectoryServices.DirectoryEntry object that is returned is held in the $objOU variable. We use this object on the last line of the script to call the SetInfo() method to write the new object into the Active Directory database. The entire image from book CreateOU.PS1 script is shown here.

image from book CreateOU.PS1

 $strCLass = "organizationalUnit" $StrOUName = "ou=MyTestOU" $objADSI = [ADSI]"LDAP://dc=nwtraders,dc=msft" $objOU = $objADSI.create($strCLass, $StrOUName) $objOU.setInfo()

ADSI Providers

Table 7-1 lists four providers available to users of ADSI. Connecting to a Microsoft Windows NT 4 system requires using the special WinNT provider. During Active Directory migrations, consultants often write a script that copies users from a Windows NT 4 domain to a Microsoft Windows Server 2003 Active Directory OU or domain. In some situations (such as with customized naming schemes), writing a script is easier than using the Active Directory Migration Tool (ADMT).

The first time I tried using ADSI to connect to a machine running Windows NT, I had a very frustrating experience because of the way the provider was implemented. Type the WinNT provider name exactly as shown in Table 7-1. It cannot be typed using all lowercase letters or all uppercase letters. All other provider names must be all uppercase letters, but the WinNT name is Pascal-cased, that is, it is partially uppercase and partially lowercase. Remembering this will save a lot of grief later. In addition, you don’t get an error message telling you that your provider name is “spelled wrong”-rather, the bind operation simply fails to connect.

Tip 

The ADSI provider names are case sensitive. LDAP is all caps; WinNT is Pascal-cased. Keep this in mind to save a lot of time in troubleshooting.

After the ADSI provider is specified, you need to identify the path to the directory target. This is where a little knowledge of Active Directory comes in handy because of the way the hierarchical naming space is structured. When connecting to an LDAP service provider, you must specify where in the LDAP database hierarchy to make the connection because the hierarchy is a structure of the database itself and not the protocol or the provider. For instance, in the image from book CreateOU.PS1 script, you create an OU that resides off the root of the domain, which is called MyTestOU. This can get confusing, until you realize that the MyTestOU OU is contained in a domain that is called NWTRADERS.MSFT. It is vital, therefore, that you understand the hierarchy with which you are working. One tool you can use to make sure you understand the hierarchy of your domain is ADSI Edit.

ADSI Edit is included in the support tools on the Windows Server 2003 disk. It is in the Support\Tools directory, and the tools are installed by clicking Suptools.msi. Installation requires Help and other programs to be closed. The installation takes only a couple of minutes and does not require a reboot. After the support tools are installed, you open a blank Micorosoft Management Console (MMC) and add the ADSI Edit snap-in. After you install the snap-in, right-click the ADSI Edit icon, select Connect To, and specify your domain, as illustrated in Figure 7-1.

image from book
Figure 7-1: Exploring the hierarchy of a forest to ensure the correct path for ADSI

LDAP Names

When specifying the OU and the domain name, you have to use the LDAP naming convention in which the namespace is described as a series of naming parts called relative distinguished names (RDNs). The RDN will always be a name part that assigns a value by using the equals sign. When you put together all the RDNs, and the RDNs of each of the ancestors all the way back to the root, you end up with a single globally unique distinguished name.

The RDNs are usually made up of an attribute type, an equal sign, and a string value. Table 7-2 lists some of the attribute types you will see when working with Active Directory. An example of a distinguished name is shown in Figure 7.2.

Table 7-2: Common Relative Distinguished Name Attribute Types
Open table as spreadsheet

Attribute

Description

DC

Domain Component

CN

Common Name

OU

Organizational Unit

O

Organization Name

Street

Street Address

C

Country Name

UID

User ID

image from book
Figure 7-2: Using the string attribute editor in ADSI Edit to quickly verify the distinguished name of a potential target for ADSI scripting

Binding

Whenever you want to do anything with ADSI, you must connect to an object in Active Directory, a process also known as binding. Think of binding as being like tying a rope around an object to enable you to work with it. Before you can do any work with an object in Active Directory, you must supply binding information. The binding string enables you to use various ADSI elements, including methods and properties. The target of the proposed action is specified as a computer, a domain controller, a user, or another element that resides within the directory structure. A binding string consists of four parts. These parts are illustrated in the following binding string from a sample script:

Open table as spreadsheet

Accelerator

Variable

Provider

ADsPath

[ADSI]

$objDomain

LDAP://

OU=hr, dc=a, dc=com

Note 

Avoid a mistake I made early on: make sure that when you finish connecting and creating, you actually commit your changes to Active Directory. Changes to Active Directory are transactional in nature, so your change will roll back if you don’t commit it. Committing the change requires you to use the SetInfo() method, as illustrated in the following line from the image from book CreateOU.ps1 script: $objOU.SetInfo(). Also keep in mind when calling a method such as SetInfo() that you must append empty parentheses () with the method call.

Working with errors

  1. Open Notepad or some other Windows PowerShell script editor.

  2. On the first line of your script, type a line that will generate an error by trying to create an object called foo. Use the variable $a to hold this object. The code to do this is shown here:

     $a = New-Object foo #creates an error

  3. Print out the value of $error.count. The count property should contain a single error when the script is run. This line of code is shown here:

     $error.count

  4. Save your script as yournameimage from book WorkWithErrors.ps1. Run your script; you should see it print out the number 1 to let you know there is an error on the Error object.

  5. The most recent error will be contained on the variable error[0]. Use this to return the CategoryInfo about the error. This code is shown here:

     $error[0].CategoryInfo

  6. Print out the ErrorDetails of the most recent error. This code is shown here:

     $error[0].ErrorDetails

  7. Print out the exception information. To do this, print out the value of the Exception property of the $error variable. This is shown here:

     $error[0].Exception

  8. Print out the Fully Qualified Error ID information. This is contained in the FullyQualifiedErrorId property of the $error variable. The code to do this is shown here:

     $error[0].FullyQualifiedErrorId

  9. Print out the invocation information about the error. To do this, use the InvocationInfo property of the $error variable. The code to do this is shown here:

     $error[0].InvocationInfo

  10. The last property to query from $error is the TargetObject property. This is shown here:

     $error[0].TargetObject

  11. Save and run your script. Notice that you will not obtain information from all the properties.

  12. The $error variable contains information about all errors that occur during the particular Windows PowerShell session, so it is quite likely to contain more than a single error. To introduce an additional error into our script. Try to create a new object called bar. Assign the object that comes back to the variable $b. This code is shown here:

     $b = New-Object bar

  13. Because we now have more than a single error on the Error object, we need to walk through the collection of errors. To do this, we can use the for statement. Use a variable called $i as the counter-variable, and proceed until you reach the value of $error.count. Make sure you enclose the statement in parentheses and increment the value of $i at the end of the statement. The first line of this code is shown here:

     for ($i = 0 ; $error.count ; $i++)

  14. Now change each of the error[0] statements that print out the various properties of the Error object to use the counter-variable $i. Because this will be the code block for the for statement, place a curly bracket at the beginning of the first statement and at the end of the last statement. The revised code block is shown here:

        {$error[$i].CategoryInfo    $error[$i].ErrorDetails    $error[$i].Exception    $error[$i].FullyQualifiedErrorId    $error[$i].InvocationInfo    $error[$i].TargetObject}

  15. Save and run your script. You will see an output that is similar to the one shown here:

     New-Object : Cannot find type [foo]: make sure the assembly containing this  type is loaded. At D:\BookDocs\WindowsPowerShell\scripts\ch7\WorkWithErrors.ps1:14 char:16  + $a = New-Object  <<<< foo #creates an error New-Object : Cannot find type [bar]: make sure the assembly containing this  type is loaded. At D:\BookDocs\WindowsPowerShell\scripts\ch7\WorkWithErrors.ps1:15 char:16  + $b = New-Object  <<<< bar #creates another error Category   : InvalidType Activity   : New-Object Reason     : PSArgumentException

  16. The first error shown is a result of the Windows PowerShell command interpreter. The last error shown with the category, activity, and reason is a result of our error handling. To remove the first runtime error, use the $erroractionpreference variable, and assign the value of “SilentlyContinue” to it. This code is shown here:

     $erroractionpreference = "SilentlyContinue"

  17. Save and run your script. You will notice that the runtime error is gone from the top of your screen.

  18. To find out how many errors are on the Error object, we can print out the value of $error.count. But just having a single number at the top of the screen would be a little confusing. To take care of that, we must add a descriptive string such as “There are currently “ + $error.count + ” errors. The code to do this is shown here:

     "There are currently " + $error.count + "errors"

  19. Save and run your script. You will notice the string prints out at the top of your script, as shown here:

     There are currently 2 errors

  20. In your Windows PowerShell Window, use the $error.clear() method to clear the errors from the Error object because it continues to count errors until a new Windows PowerShell Window is opened. This command is shown here:

     $Error.clear()

  21. Now comment out the line that creates the bar object. This revised line of code is shown here:

     #$b = New-Object bar

  22. Now save and run your script. You will notice the string at the top of your Windows PowerShell window looks a little strange. This is shown here:

     There are currently 1 errors

  23. To fix this problem, we need to add some logic to detect if there is one error or more than one error. To do this, we will use an if else statement. The first line will evaluate if the $error.count is equal to 1. If it is, then we will print out there is currently 1 error. This code is shown here:

     if ($error.count -eq 1)     {"There is currently 1 error"}

  24. We can simply use an else clause, and add curly brackets around our previous error statement. This revised code is shown here:

     else     {"There are currently " + $error.count + "errors"}

  25. Save and run the script. It should correctly detect there is only one error.

  26. Now Remove the comment from the beginning of the line of code that creates the bar object, and run the script. It should detect two errors.

  27. This concludes the working with errors procedure. If your script does not produce the desired results, compare it with the image from book WorkWithErrors.ps1 script.

Adding error handling

  1. Open the image from book CreateOU.ps1 script, and save it as yournameimage from book CreateOUwithErrorHandler.ps1.

  2. On the first line of the script, use the $erroractionpreference variable to assign the SilentlyContinue parameter. This will tell the script to suppress error messages, and continue running the script if possible. This line of code is shown here:

     $erroractionpreference = "SilentlyContinue"

  3. To ensure there are no current errors on the Error object, use the clear method. To do this, use the $error variable. This line of code is shown here:

     $error.clear()

  4. At the end of the script, use an if statement to evaluate the error count. If an error has occurred, then the count will not be equal to 0. This line of code is shown here:

     if ($error.count -ne 0)

  5. The code block to run, if the condition occurs, should print out a message stating that an error has occurred. It should also print out the CategoryInfo and Invocationinfo properties from the current $error variable. The code to do this is shown here:

     {"An error occurred during the operation. Details follow:"    $error[0].categoryInfo    $error[0].invocationinfo    $error[0].tostring()}

  6. Save and run your script. You should see an error generated (due to a duplicate attempt to create MyTestOU).

  7. Change the OU name to MyTestOU1 and run the script. You should not see an error generated. The revised line of code is shown here:

     $StrOUName = "ou=MyTestOU1"

  8. This concludes the adding error handling procedure. If you do not get the results you were expecting, compare your script with the image from book CreateOUWithErrorHandler.ps1 script.

image from book
Quick Check

Q. What is the process of connecting to Active Directory called?

A. The process of connecting to Active Directory is called binding.

Q. When specifying the target of an ADSI operation, what is the target called?

A. The target of the ADSI operation is called the ADsPath.

Q. An LDAP name is made up of several parts. What do you call each part separated by a comma?

A. An LDAP name is made up of multiple parts that are called relative distinguished names.

image from book




Microsoft Press - Microsoft Windows PowerShell Step by Step
MicrosoftВ® Windows PowerShell(TM) Step By Step (Step By Step (Microsoft))
ISBN: 0735623953
EAN: 2147483647
Year: 2007
Pages: 128
Authors: Ed Wilson

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net