locked
Adding users to AD - SetInfo error RRS feed

  • Question

  • Hi,

    I'm trying to import a load of users using the script below.  I've checked it against other examples and all looks fine but it keeps throwing up the following

    Exception calling "Invoke" with "2" argument(s): "There is no such object on the server.
    "
    At C:\Scripts\import.ps1:57 char:1
    + $objUser.Invoke("SetPassword", "password") ;
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocat
        + FullyQualifiedErrorId : DotNetMethodTargetInvocation

    Exception calling "SetInfo" with "0" argument(s): "The attribute syntax specified to the directory service is invalid.
    "
    At C:\Scripts\import.ps1:58 char:1
    + $objUser.SetInfo()
    + ~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocat
        + FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

    I'd be very grateful if anyone could look this over and see if there's anything obvious that I've missed.

    $objOU=[ADSI]“LDAP://OU=xx,DC=local,DC=xxx,DC=xxx”;
    $dataSource=import-csv “import1.csv”;
    foreach($dataRecord in $datasource)
    {

    $cn=$dataRecord.displayName
    $sAMAccountName=$dataRecord.sAMAccountName
    $givenName=$dataRecord.FirstName
    $sn=$dataRecord.LastName
    $sAMAccountName=$sAMAccountName.ToLower()
    $displayName=$dataRecord.displayName
    $userPrincipalName=$sAMAccountName + “@xxx.xxx”
    $physicalDeliveryOfficeName=$dataRecord.office
    $c=$dataRecord.ccode
    $co=$dataRecord.country
    $company=$dataRecord.company
    $department=$dataRecord.department
    $description=$dataRecord.title
    $extensionAttribute2=$dataRecord.poboxtown
    $extensionAttribute3=$dataRecord.poboxpostcode
    $facsimileTelephoneNumber=$dataRecord.fax
    $l=$dataRecord.office
    $mobile=$dataRecord.mobile
    $postalcode=$dataRecord.postalcode
    $postOfficeBox=$dataRecord.postOfficeBox
    $streetAddress=$dataRecord.streetAddress
    $telephoneNumber=$dataRecord.telephoneNumber
    $objUser=$objOU.Create(“user”, ”CN=”+$cn)

    $objUser.Put(“sAMAccountName”,$sAMAccountName)
    $objUser.Put(“userPrincipalName”,$userPrincipalName)
    $objUser.Put(“displayName”,$displayName)
    $objUser.Put(“givenName”,$givenName)
    $objUser.Put(“sn”,$sn)
    $objUser.Put(“physicalDeliveryOfficeName”,$physicalDeliveryOfficeName)
    $objUser.Put(“c”,$c)
    $objUser.Put(“co”,$co)
    $objUser.Put(“company”,$company)
    $objUser.Put(“department”,$department)
    $objUser.Put(“description”,$description)
    $objUser.Put(“title”,$description)
    $objUser.Put(“extensionAttribute2”,$extensionAttribute2)
    $objUser.Put(“extensionAttribute3”,$extensionAttribute3)
    $objUser.Put(“facsimileTelephoneNumber”,$facsimileTelephoneNumber)
    $objUser.Put(“l”,$l)
    $objUser.Put(“mobile”,$mobile)
    $objUser.Put(“postalcode”,$postalcode)
    $objUser.Put(“postOfficeBox”,$postOfficeBox)
    $objUser.Put(“streetAddress”,$streetAddress)
    $objUser.Put(“telephoneNumber”,$telephoneNumber)

    $objUser.userAccountControl = 512
    $objUser.Invoke("SetPassword", “password”) ;
    $objUser.SetInfo()
    }

    Thanks in advance

    Thursday, April 18, 2013 4:05 AM

Answers

  • I find it best to create user objects and assign the mandatory attributes (cn and sAMAccountName), then invoke SetInfo to make sure requirements are met:

    • The value of cn must be unique in the OU/container
    • cn limited to 64 characters
    • Some characters in cn must be escaped with the backslash escape character: , \ # + < > ; " =    (plus any leading or trailing spaces)
    • sAMAccountName must be unique in the domain
    • sAMAccountName limited to 20 characters
    • Following not allowed in sAMAccountName: " [ ] : ; | = + * ? < > / \ ,

    Then after the initial SetInfo you can assign values to the other optional attributes, which have almost no restrictions, and invoke SetInfo again. Except, that the SetPassword method is immediate, so the object must exist in AD when it is invoked.

    However, another issue is that you cannot assign null values to any attribute. To take this into account I always check for nulls (or blanks) before assigning attributes. Makes for a lot of if statements, but avoids problems.

    I'm thinking these possible issues may account for what you experience. But, if you get errors attempting to create a specific user, then you reboot and then can create the exact same user with the same csv values, then you have bigger problems. The only possible explanation (I can think of quickly) is that you are hitting a different DC and for some reason some DC's have big problems.

    Finally, the error "no such object on the server" should mean that the object reference $objUser is null. I have seen where this happens and you don't see any indication of it until you invoke SetInfo. If you are adding SetInfo statements, and each raises an error, then the problem must be before the first SetInfo. I would guess that the Create method failed, so $objUser is null. If so, then the requirements for mandatory attributes above were not met. And, if you invoke SetInfo before assigning sAMAccountName, the system (after Windows Server 2000) will assign an arbitrary, random appearing value to this attribute. You can later assign a better value.


    Richard Mueller - MVP Directory Services

    • Marked as answer by B77 Friday, April 19, 2013 2:33 AM
    Friday, April 19, 2013 12:36 AM

All replies

  • try to put $objUser.SetInfo() after each Put and see if it breaks somwhere

    here's Your script in much shorter version

    $objOU=[ADSI]“LDAP://OU=xx,DC=local,DC=xxx,DC=xxx”;
    $dataSource=import-csv “import1.csv”;
    foreach($dataRecord in $datasource)
    {
        $data = @{
            cn=$dataRecord.displayName
            sAMAccountName=$dataRecord.sAMAccountName.ToLower()
            givenName=$dataRecord.FirstName
            sn=$dataRecord.LastName
            displayName=$dataRecord.displayName
            userPrincipalName=$sAMAccountName + “@xxx.xxx”
            physicalDeliveryOfficeName=$dataRecord.office
            c=$dataRecord.ccode
            co=$dataRecord.country
            company=$dataRecord.company
            department=$dataRecord.department
            description=$dataRecord.title
            extensionAttribute2=$dataRecord.poboxtown
            extensionAttribute3=$dataRecord.poboxpostcode
            facsimileTelephoneNumber=$dataRecord.fax
            l=$dataRecord.office
            mobile=$dataRecord.mobile
            postalcode=$dataRecord.postalcode
            postOfficeBox=$dataRecord.postOfficeBox
            streetAddress=$dataRecord.streetAddress
            telephoneNumber=$dataRecord.telephoneNumber
        }
    $objUser=$objOU.Create(“user”, ”CN=”+$cn)
    
    $data.getEnumerator() | ForEach-Object {
        $objUser.Put($_.Key, $_.Value)
        $objUser.SetInfo()
    }
    
    $objUser.Invoke("SetPassword", “password”)
    $objUser.userAccountControl = 512
    $objUser.SetInfo()
    $objUser.PSBase.InvokeSet('AccountDisabled', $false)
    }

    Thursday, April 18, 2013 5:57 AM
  • The problem is that the SetPassword method requires that the object be in AD, but your new user object is not saved to AD until you invoke the SetInfo method. Until then, the object only exists in local memory. You need at least one SetInfo before invoking SetPassword.


    Richard Mueller - MVP Directory Services

    • Marked as answer by B77 Thursday, April 18, 2013 10:40 PM
    • Unmarked as answer by B77 Thursday, April 18, 2013 10:59 PM
    Thursday, April 18, 2013 10:16 AM
  • Cheers guys.  It's odd, I did a one line test import and it worked fine.  Tried again with a larger one and again got the setinfo error.  Seems to work ok once then never again until the server is rebooted.

    Then put setinfo after every put command and it threw up "the attribute syntax specified to the directory service is invalid"  for each put instance. 

    Thursday, April 18, 2013 11:03 PM
  • I find it best to create user objects and assign the mandatory attributes (cn and sAMAccountName), then invoke SetInfo to make sure requirements are met:

    • The value of cn must be unique in the OU/container
    • cn limited to 64 characters
    • Some characters in cn must be escaped with the backslash escape character: , \ # + < > ; " =    (plus any leading or trailing spaces)
    • sAMAccountName must be unique in the domain
    • sAMAccountName limited to 20 characters
    • Following not allowed in sAMAccountName: " [ ] : ; | = + * ? < > / \ ,

    Then after the initial SetInfo you can assign values to the other optional attributes, which have almost no restrictions, and invoke SetInfo again. Except, that the SetPassword method is immediate, so the object must exist in AD when it is invoked.

    However, another issue is that you cannot assign null values to any attribute. To take this into account I always check for nulls (or blanks) before assigning attributes. Makes for a lot of if statements, but avoids problems.

    I'm thinking these possible issues may account for what you experience. But, if you get errors attempting to create a specific user, then you reboot and then can create the exact same user with the same csv values, then you have bigger problems. The only possible explanation (I can think of quickly) is that you are hitting a different DC and for some reason some DC's have big problems.

    Finally, the error "no such object on the server" should mean that the object reference $objUser is null. I have seen where this happens and you don't see any indication of it until you invoke SetInfo. If you are adding SetInfo statements, and each raises an error, then the problem must be before the first SetInfo. I would guess that the Create method failed, so $objUser is null. If so, then the requirements for mandatory attributes above were not met. And, if you invoke SetInfo before assigning sAMAccountName, the system (after Windows Server 2000) will assign an arbitrary, random appearing value to this attribute. You can later assign a better value.


    Richard Mueller - MVP Directory Services

    • Marked as answer by B77 Friday, April 19, 2013 2:33 AM
    Friday, April 19, 2013 12:36 AM
  • I've managed to successfully import I'd say about half the list before the error appeared again. Some of the users imported did have fields within the CSV that weren't populated and yet still imported without problems.

    I've been scouring the csv for any anomalies but nothing as of yet.

    Friday, April 19, 2013 1:32 AM
  • Hi Richard, you were right it looks like it was the null values. It's odd that the first half of users, some with null values, imported.  Anyway, all good.

    Thanks for your help.

    Friday, April 19, 2013 2:34 AM