Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

How can I list all Read Only Domain Controllers that are listed in Active Directory using VBScript?

share|improve this question
    
the post by matthewk is the reason not to use vbs anymore to verbose and if you were not cutting and pasting you'd be troubleshooting it for awhile. –  tony roth Mar 8 '12 at 20:53
1  
single line command dsquery * domainroot -filter "(&(objectCategory=computer)(msDS-IsRodc=true))" -attr cn -limit 0 –  tony roth Mar 8 '12 at 20:58
add comment

2 Answers

http://www.msresource.net/code/find_all_read_only_domain_controllers_%28rodc%29_in_the_domain.html

' *********************************************************
' DS-Ex-FindAllRODCs V01.00.00vbs
' 
' Example script to illustrate how to locate all RODCs in
' a forest.  Script is more lengthy than expected due to 
' error handling, debug info., etc.
' 
' Version:  V01.00.00vbs
' Written:  03-12-2007
' 
' *********************************************************

Option Explicit

' Variant used as a constant to determine whether or not the
' print sub-routine should actually print to the screen (console)
Dim printInfoToConsole : printInfoToConsole = True
Dim printDebugInfoToConsole : printDebugInfoToConsole = False


' ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** 
'   ----- MAIN BODY OF SCRIPT -----

On Error Resume Next
    Dim dse : Set dse = GetObject("LDAP://RootDSE")
    Dim result : result = verifyError(Err)
    If Not result Then printDirectoryInfo(dse)
On Error Goto 0

' testing only
Dim hostname : hostname = dse.get("dNSHostName")
Dim rodc, rodcs() : rodcs = getRODCs(hostname)
For Each rodc In rodcs
    print(rodc)
Next

'   ----- END OF "MAIN" (subs and funcs follow)
' ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** 


Private Function getRODCs(targetHostname) ' as String()
    Dim rootDse, connection, command, recordSet
    Dim ldapQuery, ldapBase, ldapFilter, ldapAttrs, ldapScope ' as string

    If Not ((targetHostname = "") And (Right(targetHostname, 1) = "/"))Then
        targetHostname = targetHostname & "/"
    End If

    Set rootDse = GetObject("LDAP://" & targetHostname & "RootDSE")
    Set connection = CreateObject("ADODB.Connection")
    Set command = CreateObject("ADODB.Command")

    ' define filter
    ldapBase    = "<GC://" & rootDse.get("rootDomainNamingContext") & ">;"
    ldapFilter= "(&(objectCategory=computer)(msDS-IsRodc=true));"
    ldapAttrs   = "distinguishedName,cn,memberOf,displayName;"
    ldapScope   = "SubTree"

    ldapQuery   = ldapBase & ldapFilter & ldapAttrs & ldapScope

    ' configure ADO
    connection.provider = "ADsDSOObject"
    connection.open "Active Directory Provider"

    command.activeConnection = connection
    command.CommandText = ldapQuery

    command.properties("Page Size") = 100
    command.properties("Size Limit") = 10000
    command.properties("Cache Results") = False

    ' execute the command
    Set recordSet = command.execute

    If(recordSet.EOF)Then quit"No RODCs in the forest"
    recordSet.MoveFirst

    While Not recordSet.EOF
        Dim i, j ' as int

        If Not IsNull(recordSet.fields("distinguishedName").value)Then _
            print "DN: " & recordSet.Fields("distinguishedName").Value

        For i = 1 To recordSet.Fields.Count - 1
            If(TypeName(recordSet.Fields(i).Value) = "Variant()" And Not (IsNull(recordSet.Fields(i).Value)))Then
                print "  " & recordSet.Fields(i).Name & " ("  & _
                    UBound(recordSet.Fields(i).Value) & "):"

                Dim item : For Each item In recordSet.Fields(i).Value
                    print "    > " & item
                Next

                print ""
            Else
                    print "  " & recordSet.Fields(i).Name & ": " & recordSet.Fields(i).Value

            End If
        Next

        print""
        recordSet.MoveNext
    Wend

    ' testing
    Dim str() : getRODCs = str
End Function


' *******************************************************************
' Print-Directory-Info
' 
' Sub prints the DC that is being used and the level of the 
' directory service, e.g. Win2003 or ADAM
' 
' 
' Note.  Sub calls function Get-DS-Functionality
' 
' *******************************************************************
Private Sub printDirectoryInfo(oRootDse)
    Dim sServer, sDSFunctionality

    sServer = oRootDse.get("dNSHostName")
    sDSFunctionality = _
        getDSFunctionality(oRootDse.get("domainControllerFunctionality"), _
            oRootDse.get("supportedCapabilities"))

    print"Using server: " & sServer
    print"Directory: " & sDSFunctionality & vbCrLf
End Sub



' *******************************************************************
' Get-DS-Functionality
' 
' Get the domain functional level for info. purposes.  Function 
' returns a string defining the current value of the DC queried 
' (via serverless bind)
' 
' *******************************************************************
Private Function getDSFunctionality(iDSFunctionality, _
        cSupportedCapabilities)

    ' supportedCapability of an ADAM directory.  Presence indicates AD LDS
    Const LDAP_CAP_ACTIVE_DIRECTORY_ADAM_OID = "1.2.840.113556.1.4.1851"

    ' supportedCapability of an RODC.  Presence indictes DS is RO
    Const ACTIVE_DIRECTORY_PARTIAL_SECRETS  = "1.2.840.113556.1.4.1920" ' as string

    Dim oBase, dsf, nTMixedDomain, supportedCapability, ldsFlag, rodcFlag
    ldsFlag = False
    rodcFlag = False

    For Each supportedCapability In cSupportedCapabilities
        If(supportedCapability = _
            LDAP_CAP_ACTIVE_DIRECTORY_ADAM_OID)Then _
                ldsFlag = True

        If(supportedCapability = _
            ACTIVE_DIRECTORY_PARTIAL_SECRETS)Then _
                rodcFlag = True
    Next

    If(ldsFlag)Then
        If(iDSFunctionality > 2)Then
            dsf = "Active Directory Lightweight Directory Services (AD LDS)"
        Else
            dsf = "Active Directory Application Mode (ADAM)"
        End If
    Else
        Select Case iDSFunctionality
            Case 0
                Set oBase = oRootDse.get("defaultNamingContext")
                nTMixedDomain = oBase.get("nTMixedDomain")

                If(nTMixedDomain=1)Then
                    dsf = "Windows 2000 Native"
                Else
                    dsf = "Windows 2000 Mixed"
                End If

            Case 1
                dsf = "Windows Server 2003 Interim"

            Case 2
                dsf = "Windows Server 2003"

            Case 3
                dsf = "Windows Server 2008"

        End Select
    End If

    If(rodcFlag)Then dsf = dsf  & " (RODC)"

    getDSFunctionality = dsf
End Function


' Verify-Error(ByVal _err as Error-Object)
' 
' Function checks to see if the passed error object is in
' an error state and, if so, returns TRUE, otherwise
' returns FALSE
' 
Private Function verifyError(oErr)
    Dim inErrorState : inErrorState = False

    If(oErr.number <> 0)Then _
        inErrorState = True

    dbgPrint"Verify-Error::inErrorState=" & inErrorState

    verifyError = inErrorState
End Function


' Handle-Error(ByVal _err as Error-Object)
' 
' Sub prints the error number and, if present, description
' to the console if the passed argument print is enabled 
' and terminates, if the passed argument fatal is enabled.
' 
Private Sub handleError(oErr, fatal, shouldPrint)
    On Error Goto 0

    dbgPrint"Handle-Error::shouldPrint=" & shouldPrint
    dbgPrint"Handle-Error::fatal=" & fatal

    Dim errorMessage ' as string
    errorMessage = "Error: " & oErr.number

    If Not (oErr.description="")Then _
        errorMessage = errorMessage & "Details: " & _
            oErr.description & vbCrLf

    If(shouldPrint)Then print errorMessage

    If(fatal)Then 
        print vbCrLf & "Error requires premature termination.  " & _
            "Exiting script..." & vbCrLf

        WScript.Quit(-1)
    End If
End Sub

' Print(ByVal printStr as String)
'  
' Sub prints the passed string to the console if the constant-
' esq variant Print-Info-To-Console is TRUE.  Otherwise the
' passed string is logged (if implemented) or ignored.
' 
Private Sub print(printStr)
    If(printInfoToConsole)Then
        WScript.Echo(printStr)
    Else
        ' code to write to file goes here...
    End If  
End Sub

Private Sub dbgPrint(debugStr)
    If(printDebugInfoToConsole)Then _
        WScript.Echo(" [script-debug-string] " & debugStr)
End Sub


Private Sub quit(quitStr)
    print(quitStr)
    WScript.Quit(0)
End Sub
share|improve this answer
    
Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference. –  Iain Mar 8 '12 at 20:28
add comment
$filter = “(&(ObjectClass=attributeSchema)(SearchFlags:1.2.840.113556.1.4.803:=512))”   

or as listed in the other post

$filter = "(&(objectCategory=computer)(msDS-IsRodc=true))"   

$ds = New-Object DirectoryServices.DirectorySearcher([ADSI]"",$filter)  
$ds.PageSize = 1000  
$rodc = $ds.FindAll()  
$rodc 

powershell version but I can't test it right now

share|improve this answer
1  
+1 The nice thing about learning how to use LDAP queries is that not only are they very flexible, but they may be used in may different scripting/programming languages. –  jscott Mar 9 '12 at 0:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.