views:

1244

answers:

3

I'm trying to create nested Organizational Units in Active Directory and I'm close to having this working. I have a problem line below that I need help with. I'm checking if an OU exists and if not I need to create it, strOUArray contains OU=Test OU=Test2 and OU=Test3. I need the code to create OU=Test first and then use this as the parent OU on the //PROBLEM LINE below allowing the next OU OU=Test2 to be created inside OU=Test. Currently in the code below all OU's would be created in the root as I don't know how to use the first created OU in //PROBLEM LINE. I've tried using:

parent = new DirectoryEntry("LDAP://" + strOUArray[x-1] + "," + dcSubString); //note x-1

This fails as the parent doesn't exist for the first OU to be created in. Any help really appreciated, I've a tight deadline and just need to move away from this so thank you for any help.

String strOUs = container.Substring(0, container.IndexOf(@",DC="));
int dcIndex = container.IndexOf("DC=");
string dcSubString = container.Substring(dcIndex); //dcSubString = DC=Internal,DC=Net
string[] strOUArray = strOUs.Split(new Char[] { ',' });

for (int x = 0; x < strOUArray.Length; x++)
{
if (DirectoryEntry.Exists("LDAP://" + strOUArray[x] + "," + dcSubString))
 {

 }
else
 {
 DirectoryEntry objOU;
 DirectoryEntry parent = new DirectoryEntry("LDAP://" + dcSubString); //PROBLEM LINE

 objOU = parent.Children.Add(strOUArray[x], "OrganizationalUnit");
 objOU.CommitChanges();
 }
}
+1  A: 

Seems like your //PROBLEM LINE is leaving strOUArray[x] out of the string concatenation. Was that a typo when posting?

Also this snippet:

DirectoryEntry parent = new DirectoryEntry();
parent = new DirectoryEntry("...");

You're creating a DirectoryEntry and then immediately throwing away the reference to it on the next line.

ecoffey
Hi ecoffey, I've edited the code to fix throwing away the DirectoryEntry, thanks for that. As I mention in my first post I can't use strOUArray[x] on the //problem line as the first item in the array won't exist so I can't create an OU in this parent location. Do you have any further thoughts? Thx
A: 

Hi Jade,

Well, I guess, I would try to do something like this:

  • bind to the top-level first (that's LDAP://
  • create the first OU
  • then recursively
    • bind to the container just created
    • add the next level down
    • repeat until you're done

Something like this (untested - I don't have a server here to check it out):

String strOUs = container.Substring(0, container.IndexOf(@",DC="));
int dcIndex = container.IndexOf("DC=");
string dcSubString = container.Substring(dcIndex); //dcSubString = DC=Internal,DC=Net
string[] strOUArray = strOUs.Split(new Char[] { ',' });

// create a bind path which we'll build up
string ldapPath = dcSubString;

// bind to the top-level container
DirectoryEntry workEntry = new DirectoryEntry("LDAP://" + ldapPath);

// loop through all sub-OU's to create
foreach(string currentOU in strOUArray)
{
  // add the next OU below the current entry
  objOU = workEntry.Children.Add(currentOU, "OrganizationalUnit");
  objOU.CommitChanges(); 

  // bind to the newly created OU
  ldapPath = currentOU + "," + ldapPath;
  workEntry = new DirectoryEntry("LDAP://" + ldapPath);
}

There's one catch I see: if you create a new OU, you might not be able to bind to it right away - sometimes it takes a moment to propagate into the directory.

Does this help?

Marc

marc_s
A: 

Having run into something similar in the past I created a function that would return the directory object, either newly created or existing (sorry it's in VBScript):

Function GetOU(objParentOU, strOUName)
    On error resume next
    Set GetOU = Nothing

    objParentOU.Filter = Array("organizationalUnit")
    Dim OU : Set OU = Nothing
    For Each OU in objParentOU
        if lcase(OU.Name) = lcase("ou=" & strOUName) then
            wscript.echo "Connected to existing OU: " & OU.Name
            set GetOU = GetObject(OU.adsPath)
            exit function
        end if
    Next
    Set OU = Nothing

    ' If script made it to here then the OU must not already exist
    Set GetOU = objParentOU.Create("organizationalUnit", "ou=" & strOUName)
    GetOU.SetInfo

    if err then
        wscript.echo err.description
        err.clear
    else
        wscript.echo "Created new OU: " & strOUName
    end if
end function

Using this I can build my chain without regard for the OU existing or not. First set the base path and then add on top of that:

Set objDomain = GetObject(LDAP_CONNECTION_STRING)
Set parentOU = GetOU(objDomain, "parentOU")
Set childOU = GetOU(parentOU, "childOU")
Set subchildOU = GetOU(childOU, "subchildOU")

As the code works down the set commands the OU's are either created new or bound-to if they already exist.

Dscoduc