One of my clients has a common problem. Over the last few years in the NT 4.0 world, too many people had become members of the Domain Admins group. Branch administrators were added because they needed to manage servers and user accounts. Help desk and desktop support staff were added, because no one wanted to visit hundreds (or even thousands) of PCs to add another group to the local Administrators group.
After implementing Active Directory, this client then wanted to begin removing users from the Domain Admins group. Delegation of authority and regional domains takes care of the branch administrators, but how do you grant local PC access to help desk and support staff? A separate group (Desktop Admins, for example) must be added to the local Administrators group on every PC in the organization. That'll take a lot of work... or will it? Not if we use a script.
Finding the computer accounts
The most difficult part of this task is to determine the list of computers you want to modify. You'll want to leave out member servers and domain controllers. If you have a distributed management team, you may even have multiple groups of administrators to add to different groups of computers.
In my client's case, they wanted to modify all PCs (nothing running a server operating system). I chose to write a quick little script to output every computer in the domain, along with the operating system recorded in the computer account. Here it is.
1: Const ADS_SCOPE_SUBTREE = 2
2: Set objConnection = CreateObject("ADODB.Connection")
3: Set objCommand = CreateObject("ADODB.Command")
4: objConnection.Provider = "ADsDSOObject"
5: objConnection.Open "Active Directory Provider"
6: Set objCommand.ActiveConnection = objConnection
7: objCommand.CommandText = "Select Name, operatingSystem
from 'LDAP://DC=Domain,DC=com' where " & _"objectClass='computer'"
8: objCommand.Properties("Page Size") = 1000
9: objCommand.Properties("Timeout") = 30
10: objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
11: objCommand.Properties("Cache Results") = False
12: Set objRecordSet = objCommand.Execute
14: Do Until objRecordSet.EOF
15: Wscript.Echo objRecordSet.Fields("Name").value
& vbTab & _ objRecordSet.Fields("operatingSystem").Value
This script, unlike the script to add global groups to computers, does require Active Directory. You'll need to modify line 7 to put in the domain name for your domain. Then just output the results of this script to a text file, and you'll have a tab-delimited text file that you can import into Excel. To output the results of the script to a text file, execute the script from a command prompt:
cscript scriptname.vbs > computers.txt
Once you've imported the file into Excel, you can sort by operating system and remove all the rows that list a server-based operating system, such as Windows 2000 Server or Windows Server 2003. You should be left with all of the PCs. This is the input list we'll use for the primary script.
Your requirements may differ from that of my client. Be sure to carefully review the list of devices that you want to modify.
Adding the global group to the local group
Now that we have the list of PCs we want to modify, let's take a look at the script we'll use to make the changes. First, let's look at the three lines that you'll need to modify before running the script, so that it matches your environment.
20: Const strDomain = "YOURDOMAINHERE" ' Enter your NetBIOS
domain name here
21: Const strGlobalGroup = "Desktop Admins" ' Enter the domain
global group name here
22: Const strLocalGroup = "Administrators" ' Enter the local
group name here
Edit line 20 to be the NetBIOS name of your domain. Line 21 should be the name of the global group that you want to add to the local group of the PCs. Finally, line 22 is the name of the local group on the PCs.
26: Const inFilename = "Computers.txt" ' Input file name
containing list of computers
27: Const outFilename = "AddGlobal2Local.log" ' Log file name
containing results of operation
After initializing variables and opening our files, we're ready for the heart of the script: connecting to each computer and adding the global group to the local group.
42: Set objGlobalGroup = GetObject
("WinNT://" & strDomain & "/" & strGlobalGroup & ",group")
43: If Err.Number <> 0 Then
44: outFile.writeline Now & vbTab & " Error connecting to "
& strDomain & "/" & _
45: strGlobalGroup & " —- " & Err.Description
48-69: <Do the script here>
70: End If
Line 42 establishes a connection to the global group. Lines 43 trough 47 and line 73 do our error checking. If an error occurs, such as a misspelling of the global group name or the domain name, the error will be written to the log and the script will exit gracefully. If there is no error, lines 48 through 72 will execute.
48: While Not
vbTab, -1, 1)
50: ' arrayAccountNames(0) contains the computer
account name (to modify)
51: strComputerName = arrayAccountNames(0)
52: ' Connect to the computer's local group
53: Set objLocalGroup = GetObject("WinNT://"
& strComputerName & "/" & strLocalGroup & ",group")
54: If Err.Number <> 0 Then
55: outFile.writeline Now & vbTab
& "Error connecting to " & _
56: strComputerName & "/"
& strLocalGroup & " —- " & Err.Description
59: ' Add the global group to the local group
on the computer
61: If Err.Number <> 0 Then
62: outFile.writeline Now & vbTab & _
63: "Error adding the global group
to the local group on " & _
& " —- " & Err.Description
67: outFile.writeline (Now & vbTab & _
68: "Global group successfully
added to local group on " & _
69: strComputerName & ".")
70: End If
71: End If
Lines 48 and 72 set up the loop that goes through each computer name in the input file, while lines 49 and 51 actually grab the computer name and put the value into a variable. Line 53 attempts to connect to the local group on the computer just pulled from the file. This is where error checking becomes crucial to the execution of the script, because there are many reasons that you may not be able to connect to the PC: The computer may be offline, or you may not have proper permissions to connect to the computer. Error checking at this point allows you to log which computers could not be connected, and then continue on to the next computer, rather than just stopping the script in its tracks with a run-time error.
Line 60 attempts to actually add the global group to the computer's local group. Again, we have error checking and logging, so we know whether the execution was successful or not.
Finally, the last few lines of the script mark the log, close the files, and let the user know that the script has completed. Note that the number of computers in the input file and the percentage of computers offline or unavailable will have a great effect on how long this script will take to execute. The script will try to connect to offline or unreachable PCs for about 30 seconds before they timeout. Several hundred PCs could take up to several hours to fully complete.
When the script has completely executed, the log file will contain one line for each computer, stating whether the execution was successful or not. You may wish to take this list and run the script again later, to catch PCs that have come back online or that may have had connectivity reestablished. Here's a quick way to get a list of just the failed PCs. Using the log, execute the following command:
find /i "error" AddGlobal2Local.log > ErrorPCs.txt
Then use a text editor or spreadsheet program to filter out the error messages in the log, just leaving the computer names. Repeat this process as often as necessary.
This script builds upon the same principles as the two prior articles in this series. Be sure to check these out, since they go into more detail on certain parts of the foundation script, as well as provide links to VBScript editors and other vital scripting information: