ADPREP /DOMAINPREP failures

I am putting forth my investigation into this problem and the solution I found hoping it will be helpful to others in similar Scenarios.
Note that the Fix may not be applicable if the cause of failure is any bit different to what I faced.
I have recently upgraded one of my customer’s environments AD to Windows server 2008 R2 from 2003 server
During the course of this activity, command ADPREP / DOMAINPREP returned with the following error statement.
Error Code:
Message: 000020B5: AtrErr: DSID-03152395, #1: 0: 000020B5:
DSID-03152395, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 9054f (otherWellKnownObjects).

The error code returns 0x13 DSID-03152395 in log file has to be converted to readable format using the tool DSID.exe and is available only with Microsoft and is not for general public. After decoding the code with the help of MS, i have come up with below findings based on the status message. 
What caused the Failure?
The execution of adprep /domainprep will work on the various domain wide operations to make the domain configuration changes to adapt for W2K8 R2. In that, one of the operations will be to create Managed Service Accounts container in AD.
Windows Server 2008 R2 introduces a new type of Container account called a Managed Service Accounts that assists in the endpoint administration. In a way, a managed service account can function like the Built-in organizational unit in default domain configurations.
The error cited in the Adprep.log indicated that domain configuration attribute could not be populated, and this is because of the Managed Service Accounts container already being present in the current AD.
By chance or mistake, we had an OU called” managed service account” in 2k3 environment.  Hence while preparing the AD, there is a conflict in creating the Managed service account OU by system command.

What fixed the failure?

Delete the Managed service accounts OU from windows 2003 AD and then run the adprep domainprep.
Don’t rename the OU, because, chances of solving the issue by renaming the OU are very slim.
So better delete it.
Action to be performed:
          Take a system state backup on all domain controllers.
          Move the contents of the Managed service account OU to another OU.
          When all users and sub OU have been, delete the OU.

Then run adprep domainprep and it should complete without errors.

Extract Active Directory group membership details


The steps below should help you extract the Group Membership details from Active directory using saved queries.

Note that It requires DN (distinguished Name) name of a group to extract the members details.

1.     Open ADSIEdit.msc and locate the group.

2.     View the properties of the group to reveal the distinguishedName attribute value and copy to the clipboard.




Next, open DSA.msc ( Active directory users and computers)

1.     Right-Click saved queries and select a new query and define a name for your query \”EX: Account members\”.

2.     Select define query and  then Select Users, Contacts, and Groups from the Find: drop-down list.

3.     Go to Advanced tab and click the user Member Of with the condition of is (exactly)\”, paste the group\’s distinguishedName into the field and click Add.

4.     Click OK and then refresh the query by pressing F5 to retrieve the details.


VB script to remove Inactive machines from domain

I came across this very helpful article on \” finding inactive computers in a Domain\” , Thanks to Awinish – Directory service MVP. found it worth to share with others.

The very good script by Richard L. Mueller to find stale computer records in your domain, i used many times for different client & it worked like charm. It can be run on member server too.
You have to modify the script for your requirement like no of days & Domain name where you want to run the script.
The script will disable all the stale computer & move to the OU named as Inactive & later on you check the log file which is created in C drive named as MyFolder.
Test the script on your lab & then use it on your own risk.
Please save the attached script as MoveOldComputers.vbs from Inactive Computers.doc
Before running the script in your domain, create a OU named as Inactive & also create a folder names MyFolder in c drive in the member system you are trying to run the script.
C:\\MyFolder

—————————————-Script————————————————————

\’ MoveOldComputers.vbs
\’ VBScript program to determine when each computer account in the domain
\’ last had their password changed. If this date is more than a specified
\’ number of days in the past, the computer object is considered inactive
\’ and it is moved to a target Organizational Unit. The computer account
\’ is also disabled. A log file keeps track of which computer objects are
\’ moved.
\’
\’ ———————————————————————-
\’ Copyright (c) 2004 Richard L. Mueller
\’ Hilltop Lab web site – http://www.rlmueller.net
\’ Version 1.0 – February 8, 2004
\’ Version 1.1 – February 23, 2004 – Bug fix.
\’ Version 1.2 – July 6, 2007 – Modify how IADsLargeInteger interface
\’                              is invoked.
\’ Version 1.3 – July 31, 2007 – Escape any \”/\” characters in computer
\’                               DNs.
\’
\’ You have a royalty-free right to use, modify, reproduce, and
\’ distribute this script file in any way you find useful, provided that
\’ you agree that the copyright owner above has no warranty, obligations,
\’ or liability for such use.
Option Explicit
Dim strFilePath, objFSO, objFile, adoConnection, adoCommand
Dim objRootDSE, strDNSDomain, strFilter, strQuery, adoRecordset
Dim strComputerDN, objShell, lngBiasKey, lngBias
Dim objDate, dtmPwdLastSet, k
Dim intDays, strTargetOU, objTargetOU, objComputer
Dim intTotal, intInactive, intNotMoved, intNotDisabled
\’ Specify the log file. This file will be created if it does not
\’ exist. Otherwise, the program will append to the file.
strFilePath = \”c:\\MyFolder\\OldComputers.log\”
\’ Specify the minimum number of days since the password was last set for
\’ the computer account to be considered inactive.
intDays = 180
\’ Specify the Distinguished Name of the Organizational Unit into
\’ which inactive computer objects will be moved.
strTargetOU = \”ou=Inactive,dc=contoso,dc=com\”
\’ Bind to target Organizational Unit.
On Error Resume Next
Set objTargetOU = GetObject(\”LDAP://\” & strTargetOU)
If (Err.Number 0) Then
    On Error GoTo 0
    Wscript.Echo \”Organization Unit not found: \” & strTargetOU
    Wscript.Quit
End If
On Error GoTo 0
\’ Open the log file for write access. Append to this file.
Set objFSO = CreateObject(\”Scripting.FileSystemObject\”)
On Error Resume Next
Set objFile = objFSO.OpenTextFile(strFilePath, 8, True, 0)
If (Err.Number 0) Then
    On Error GoTo 0
    Wscript.Echo \”File \” & strFilePath & \” cannot be opened\”
    Set objFSO = Nothing
    Wscript.Quit
End If
On Error GoTo 0
\’ Obtain local time zone bias from machine registry.
Set objShell = CreateObject(\”Wscript.Shell\”)
lngBiasKey = objShell.RegRead(\”HKLM\\System\\CurrentControlSet\\Control\\\” _
    & \”TimeZoneInformation\\ActiveTimeBias\”)
If (UCase(TypeName(lngBiasKey)) = \”LONG\”) Then
    lngBias = lngBiasKey
ElseIf (UCase(TypeName(lngBiasKey)) = \”VARIANT()\”) Then
    lngBias = 0
    For k = 0 To UBound(lngBiasKey)
        lngBias = lngBias + (lngBiasKey(k) * 256^k)
    Next
End If
\’ Use ADO to search the domain for all computers.
Set adoConnection = CreateObject(\”ADODB.Connection\”)
Set adoCommand = CreateObject(\”ADODB.Command\”)
adoConnection.Provider = \”ADsDSOOBject\”
adoConnection.Open \”Active Directory Provider\”
Set adoCommand.ActiveConnection = adoConnection
\’ Determine the DNS domain from the RootDSE object.
Set objRootDSE = GetObject(\”LDAP://RootDSE\”)
strDNSDomain = objRootDSE.Get(\”DefaultNamingContext\”)
\’ Filter to retrieve all computer objects.
strFilter = \”(objectCategory=computer)\”
\’ Retrieve Distinguished Name and date password last set.
strQuery = \”;\” & strFilter _
    & \”;distinguishedName,pwdLastSet;subtree\”
adoCommand.CommandText = strQuery
adoCommand.Properties(\”Page Size\”) = 100
adoCommand.Properties(\”Timeout\”) = 30
adoCommand.Properties(\”Cache Results\”) = False
\’ Write information to log file.
objFile.WriteLine \”Search for Inactive Computer Accounts\”
objFile.WriteLine \”Start: \” & Now
objFile.WriteLine \”Base of search: \” & strDNSDomain
objFile.WriteLine \”Log File: \” & strFilePath
objFile.WriteLine \”Inactive if password not set in days: \” & intDays
objFile.WriteLine \”Inactive accounts moved to: \” & strTargetOU
objFile.WriteLine \”———————————————-\”
\’ Initialize totals.
intTotal = 0
intInactive = 0
intNotMoved = 0
intNotDisabled = 0
\’ Enumerate all computers and determine which are inactive.
Set adoRecordset = adoCommand.Execute
Do Until adoRecordset.EOF
    strComputerDN = adoRecordset.Fields(\”distinguishedName\”).Value
    \’ Escape any forward slash characters, \”/\”, with the backslash
    \’ escape character. All other characters that should be escaped are.
    strComputerDN = Replace(strComputerDN, \”/\”, \”\\/\”)
    intTotal = intTotal + 1
    \’ Determine date when password last set.
    Set objDate = adoRecordset.Fields(\”pwdLastSet\”).Value
    dtmPwdLastSet = Integer8Date(objDate, lngBias)
    \’ Check if computer object inactive.
    If (DateDiff(\”d\”, dtmPwdLastSet, Now) > intDays) Then
        \’ Computer object inactive.
        intInactive = intInactive + 1
        objFile.WriteLine \”Inactive: \” & strComputerDN _
            & \” – password last set: \” & dtmPwdLastSet
        \’ Move computer object to the target OU.
        On Error Resume Next
        Set objComputer = objTargetOU.MoveHere(\”LDAP://\” _
            & strComputerDN, vbNullString)
        If (Err.Number 0) Then
            On Error GoTo 0
            intNotMoved = intNotMoved + 1
            objFile.WriteLine \”Cannot move: \” & strComputerDN
        End If
        \’ Disable the computer account.
        On Error Resume Next
        objComputer.AccountDisabled = True
        \’ Save changes to Active Directory.
        objComputer.SetInfo
        If (Err.Number 0) Then
            On Error GoTo 0
            intNotDisabled = intNotDisabled + 1
            objFile.WriteLine \”Cannot disable: \” & strComputerDN
        End If
        On Error GoTo 0
    End If
    adoRecordset.MoveNext
Loop
adoRecordset.Close
\’ Write totals to log file.
objFile.WriteLine \”Finished: \” & Now
objFile.WriteLine \”Total computer objects found:   \” & intTotal
objFile.WriteLine \”Inactive:                       \” & intInactive
objFile.WriteLine \”Inactive accounts not moved:    \” & intNotMoved
objFile.WriteLine \”Inactive accounts not disabled: \” & intNotDisabled
objFile.WriteLine \”———————————————-\”
\’ Display summary.
Wscript.Echo \”Computer objects found:         \” & intTotal
Wscript.Echo \”Inactive:                       \” & intInactive
Wscript.Echo \”Inactive accounts not moved:    \” & intNotMoved
Wscript.Echo \”Inactive accounts not disabled: \” & intNotDisabled
Wscript.Echo \”See log file: \” & strFilePath
\’ Clean up.
objFile.Close
adoConnection.Close
Set objFile = Nothing
Set objFSO = Nothing
Set objShell = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing
Set objRootDSE = Nothing
Set adoRecordset = Nothing
Set objComputer = Nothing
Wscript.Echo \”Done\”
Function Integer8Date(objDate, lngBias)
    \’ Function to convert Integer8 (64-bit) value to a date, adjusted for
    \’ time zone bias.
    Dim lngAdjust, lngDate, lngHigh, lngLow
    lngAdjust = lngBias
    lngHigh = objDate.HighPart
    lngLow = objDate.LowPart
    \’ Account for bug in IADsLargeInteger property methods.
    If (lngHigh = 0) And (lngLow = 0) Then
        lngAdjust = 0
    End If
    lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
        + lngLow) / 600000000 – lngAdjust) / 1440
    Integer8Date = CDate(lngDate)
End Function