Migration : SIDHistory Cleanup vbScript

Migration : Cleanup SIDHistory

One of the last steps in an Actiove Directory migration is the removal of SIDHistory from migrated users, computers and groups. This will help reduce the size of the directory database.

Before cleanup of SIDHistory domain-wide, you should perform cleanup on a single OU and analyse the effects on applications such as AzMan and Sharepoint. Watch out for DCOM remote launch pernmissions. It is possible to modify the script to target individual users for this purpose.

The following VBScript will perform a SIDHistory cleanup of all user objects (this can be altered) within a particular OU. It is possible to change the LDAP filter and OU string to suit testing and cleanup of various object classes. Alternately, by changing the line strOU = “OU=UK,” to strOU = “” willl perform SIDHistory cleanupon all objects within every OU.

Remember to perform cleanup on the following objectClass types, changing the code in RED will allow you to perform cleanup of different objectClass’: User, Computer, Contact, Group.

   Const ADS_PROPERTY_DELETE = 4
   Const ADS_PROPERTY_UPDATE = 2

   Dim strFilter ‘As String
   Dim oConnection ‘As ADODB.Connection
   Dim oRecordSet ‘As ADODB.RecordSet
   Dim strQuery ‘As String
   Dim strDomainNC ‘As String
   Dim oRootDSE ‘As IADs
   Dim vArray ‘As Variant()
   Dim vSid ‘As Variant
   Dim oDirObject ‘As Variant
   Dim strOU ‘As String

   ‘ Find the domain naming context
   set oRootDSE = GetObject(“LDAP://RootDSE”)
   strDomainNC = oRootDSE.Get(“defaultNamingContext”)
   set oRootDSE = Nothing

   ‘ Setup the ADO connection
   Set oConnection = CreateObject(“ADODB.Connection”)
   oConnection.Provider = “ADsDSOObject”
   oConnection.Open “ADs Provider”
   
   ‘Target OrganizationalUnit
   strOU = “OU=UK,”
   
   ‘Target objectClass
   strFilter = “(&(objectClass=user))”
   strQuery = “;” & strFilter & “;distinguishedName,objectClass,name,sidHistory;subtree”

   ‘Execute the query
   set oRecordSet = oConnection.Execute(strQuery)

   if oRecordSet.Eof then
     WScript.Echo “No objects were found”
     WScript.Quit(0)
   Else
     Dim vClasses ‘As Variant
     Dim strClass ‘As String

     WScript.Echo “Name, Class, DN, SIDHistory”

     ‘ Iterate through the objects that match the filter
     While Not oRecordset.Eof
        vClasses = oRecordset.Fields(“objectClass”).Value
        strClass = vClasses(UBound(vClasses))
       
        If IsNull(oRecordSet.Fields(“sIDHistory”).Value ) Then
           WScript.Echo “This object does not have a sidHistory”
        Else
            set oDirObject = GetObject(“LDAP://” & oRecordset.Fields(“distinguishedName”).Value)
               vArray = oDirObject.GetEx(“sIDHistory”)
              
             For Each vSid in vArray
                   If OctetToHexStr(vSid) > “” Then
                       WScript.Echo chr(34) & oRecordset.Fields(“name”).Value & chr(34) & “,” & _
                        chr(34) & strClass & chr(34) & “,” & chr(34) & _
                        oRecordset.Fields(“distinguishedName”).Value & chr(34) & “,” & chr(34) & _
                        OctetToHexStr(vSid)    & chr(34)
                End If
            Next

            oDirObject.SetInfo
            WScript.Echo “The sidHistory has been cleared for this object!”
        End if
        WScript.Echo
        oRecordset.MoveNext
     Wend
   End if

   ‘Clean up
   Set oRecordset = Nothing
   Set oConnection = Nothing

Function OctetToHexStr(sOctet)
  Dim k
  OctetToHexStr = “”
  For k = 1 To Lenb(sOctet)
    OctetToHexStr = OctetToHexStr _
      & Right(“0” & Hex(Ascb(Midb(sOctet, k, 1))), 2)
  Next
End Function