VBScript to Add Computers To Groups

Answered VBScript to Add Computers To Groups

  • Monday, July 30, 2012 3:49 PM
     
     

    Is it possible to change the script rather than adding one group name to mulitple computers that you could have it adding multiple groups from a txt file?

All Replies

  • Monday, July 30, 2012 4:05 PM
     
     
    What script?

    Grant Ward, a.k.a. Bigteddy

  • Monday, July 30, 2012 4:14 PM
    Moderator
     
     Answered Has Code

    I split this question from this older thread (marked answered in April, 2012):

    http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/da0956bc-2cf2-49ba-a602-9231a83117ea

    The code referred to (I believe) follows:

    Option Explicit

    Dim strFile, objGroup, objFSO, objFile, strComputerDN, objComputer
    Dim objRootDSE, strDNSDomain, objTrans, strNetBIOSDomain, strComputer

    Const ForReading = 1
    ' Constants for the NameTranslate object.
    Const ADS_NAME_INITTYPE_GC = 3
    Const ADS_NAME_TYPE_NT4 = 3
    Const ADS_NAME_TYPE_1779 = 1

    ' Specify the text file of computer NetBIOS names.
    strFile = "c:\Scripts\Computers.txt"

    ' Bind to the group object.
    Set objGroup = GetObject("LDAP://cn=Test Group,ou=West,dc=MyDomain,dc=com")

    ' Determine DNS name of domain from RootDSE.
    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")

    ' Use the NameTranslate object to find the NetBIOS domain name from the
    ' DNS domain name.
    Set objTrans = CreateObject("NameTranslate")
    objTrans.Init ADS_NAME_INITTYPE_GC, ""
    objTrans.Set ADS_NAME_TYPE_1779, strDNSDomain
    strNetBIOSDomain = objTrans.Get(ADS_NAME_TYPE_NT4)
    ' Remove trailing backslash.
    strNetBIOSDomain = Left(strNetBIOSDomain, Len(strNetBIOSDomain) - 1)

    ' Open the file for read access.
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.OpenTextFile(strFile, ForReading)

    ' Read each line of the file.
    Do Until objFile.AtEndOfStream
        strComputer = Trim(objFile.ReadLine)
        ' Skip blank lines.
        If (strComputer <> "") Then
            ' Use the Set method to specify the NT format of the computer name.
            ' The sAMAccountName of the computer will be the NetBIOS name with trailing "$".
            ' Trap error if computer does not exist.
            On Error Resume Next
            objTrans.Set ADS_NAME_TYPE_NT4, strNetBIOSDomain & "\" & strComputer & "$"
            If (Err.Number <>  0) Then
                On Error GoTo 0
                Wscript.Echo "Computer " & strComputer & " does not exist"
            Else
                On Error GoTo 0
                ' Use the Get method to retrieve the Distinguished Name.
                strComputerDN = objTrans.Get(ADS_NAME_TYPE_1779)

                ' Bind to the computer object.
                Set objComputer = GetObject("LDAP://" & strComputerDN)

                ' Check if computer a member of the group.
                If (objGroup.IsMember(objComputer.ADsPath) = False) Then
                    ' Add the computer to the group.
                    objGroup.Add(objComputer.ADsPath)
                End If
            End If
        End If
    Loop

    ' Clean up.
    objFile.Close

    -----

    If your intention is to add all of the computers in the text file to the same groups, you can simply bind to all of the groups at the beginning of the script, and add statements to add all of the computers to all of the groups. You would have objGroup1, objGroup2, objGroup3, etc. Do you need help with that?

    However, if you intend to read group names from a script, that adds complications, and raises questions. I hope you don't mean a separate text file of group names, because then it must be assumed that all computers get added (potentially) to all the groups, and it would be easier to simply add the groups to the script (bind using distinguished names). If instead, you mean one text file, where each line has a computer name followed by group names, then:

    • Are both the computer names and group names NetBIOS names (pre-Windows 2000 names) or are they distinguished names?
    • Does each line have one computer name followed by one or more group names?
    • Are the names comma delimted?

    In the later case, it is possible that the same group will be bound to in the script (with a "Set" statement) many times, which is slow. The best solution would be to use a dictionary object to keep track of the group objects, so that each only needs to be bound once, no matter how many times it is used. I've done this many times in the past, so I will look for a similar script. In the meantime, clarify your question in case this is not needed.


    Richard Mueller - MVP Directory Services

  • Monday, July 30, 2012 4:51 PM
    Moderator
     
     Answered Has Code

    I found a similar script from 2007, but it dealt with users rather than computers. I modified the script, assuming your text file has one computer name (NetBIOS name) followed by one or more group names (pre-Windows 2000 name). The following has not been tested:

    Option Explicit

    Dim objFSO, objFile, strFile, strLine, arrFields
    Dim lngCount, strGroup, strComputer, objGroupList
    Dim objRootDSE, strDNSDomain, objTrans, strNetBIOSDomain
    Dim strGroupDN, strComputerDN, blnSkip, k

    Const ForReading = 1
    Const ADS_NAME_INITTYPE_GC = 3
    Const ADS_NAME_TYPE_NT4 = 3
    Const ADS_NAME_TYPE_1779 = 1

    ' Determine DNS domain name from RootDSE object.
    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.Get("DefaultNamingContext")

    ' Use the NameTranslate object.
    Set objTrans = CreateObject("NameTranslate")
    ' Initialize NameTranslate by locating the Global Catalog.
    objTrans.Init ADS_NAME_INITTYPE_GC, ""
    ' Use Set method to specify DNS domain name.
    objTrans.Set ADS_NAME_TYPE_1779, strDNSDomain
    ' Use Get method to retrieve NetBIOS name of domain.
    strNetBIOSDomain = objTrans.Get(ADS_NAME_TYPE_NT4)
    ' Remove trailing backslash.
    strNetBIOSDomain = Left(strNetBIOSDomain, Len(strNetBIOSDomain) - 1)

    ' Specify comma delimited file of computers and groups (pre-Windows 2000 names).
    strFile = "c:\scripts\ComputerGrps.csv"

    ' Setup dictionary object of groups.
    Set objGroupList = CreateObject("Scripting.Dictionary")
    objGroupList.CompareMode = vbTextCompare

    ' Use FSO to open csv file for read access.
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.OpenTextFile(strFile, ForReading)

    lngCount = 0
    ' Read the text file.
    Do Until objFile.AtEndOfStream
        strLine = Trim(objFile.ReadLine)
        lngCount = lngCount + 1
        ' Skip blank lines.
        If (strLine <> "") Then
            ' Parse line for computer name (first field in the line).
            arrFields = Split(strLine, ",")
            strComputer = Trim(arrFields(0))
            ' Use Set method to specify NT name of computer.
            ' sAMAccountName of computer is NetBIOS name with trailing "$" character.
            ' Trap error if object not found.
            On Error Resume Next
            objTrans.Set ADS_NAME_TYPE_NT4, strNetBIOSDomain & "\" & strComputer & "$"
            If (Err.Number = 0) Then
                On Error GoTo 0
                ' Retrieve distinguished name of computer.
                strComputerDN = objTrans.Get(ADS_NAME_TYPE_1779)
                ' Enumerate the group names for this computer from the line.
                For k = 1 To UBound(arrFields)
                    strGroup = Trim(arrFields(k))
                    blnSkip = False
                    ' Check if group encountered before.
                    If Not objGroupList.Exists(strGroup) Then
                        ' Use Set method to specify NT Name of group.
                        ' Trap error if group does not exist.
                        On Error Resume Next
                        objTrans.Set ADS_NAME_TYPE_NT4, strNetBIOSDomain _
                            & "\" & strGroup
                        If (Err.Number = 0) Then
                            On Error GoTo 0
                            ' Use Get method to retrieve group DN.
                            strGroupDN = objTrans.Get(ADS_NAME_TYPE_1779)
                            ' Bind to group object and add to dictionary object.
                            Set objGroupList(strGroup) = GetObject("LDAP://" _
                                & strGroupDN)
                        Else
                            On Error GoTo 0
                            ' Group does not exist.
                            WScript.echo "Group " & strGroup & " not found."
                            Wscript.Echo "Computer " & strComputer _
                                & " not added to group " _
                                & strGroup & " per line " & CStr(lngCount)
                            ' Skip processing this group.
                            blnSkip = True
                        End If
                    End If
                    If (blnSkip = False) Then
                        ' Check if computer already a member of the group.
                        If (objGroupList(strGroup).IsMember("LDAP://" & strComputerDN) = False) Then
                            ' Add the computer to the group.
                            objGroupList(strGroup).Add("LDAP://" & strComputerDN)
                        Else
                            Wscript.Echo strComputer & " already member of group " _
                                & strGroup
                        End If
                    End If
                Next
            Else
                On Error GoTo 0
                Wscript.Echo "Computer " & strComputer & " not found"
            End If
        End If
    Loop

    ' Clean up.
    objFile.Close

    -----



    Richard Mueller - MVP Directory Services