This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


This article assumes you're familiar with VBScript

Administering Windows through Windows Script Host
Vernon W. Hui

Windows Script Host, which will be part of Windows 2000, can help reduce the repetitive aspects of remote administration.
Cruising along on the information highway these days, you can't avoid the buzz about all sorts of new technology. But little seems to excite system administrators as much as Windows® Script Host (WSH) 2.0. Planned for release with Windows 2000, WSH 2.0 is a language-independent scripting host that allows administrators to write simple, powerful, and flexible scripts.
      What do network administrators hate the most? I would imagine it's the repetitiveness of their job tasks. How many times have you repeatedly copied the same files over the network or supplied the same prompts with the same answers? Unix administrators have long held the simple secret to success: writing scripts.
      Writing scripts is what WSH is all about. Since WSH is language-independent, you can choose the ActiveX® scripting engine that you are most comfortable with, whether it's Visual Basic® Scripting Edition (VBScript), JScript®, Perl, or Python. In addition, WSH supports COM, so you can take advantage of technologies external to scripting languages, such as Windows Management Instrumentation (WMI) and Active Directory™ Services Interface (ADSI).
      I'll get into WMI and ADSI in more detail, and I will assume that you have at least a general understanding of them. For more information regarding these two technologies, you can refer to http://msdn.microsoft.com/developer/sdk/wmisdk/default.asp and http://www.microsoft.com/adsi. For the purpose of these examples, I assume that you are using Windows 2000; for other platforms, you may have to install ADSI and WMI.
      WSH is not only able to exploit the strengths of different scripting languages and technologies, it also has its own powerful object model. First, I will focus on some of the built-in features of the WSH object model. Then I'll help you write your first logon script and return information via WMI. Finally, I'll show you how to put your logon scripts to use after creating some users and groups with WSH and ADSI. I've chosen to write my code in VBScript, but you can just as easily choose JScript or some other scripting language.

Using WSH and WMI to Write Logon Scripts
      As you know, logon scripts are meant to launch on startup. Figure 1 shows a logon script that detects the type of user who's logging in and performs tasks based on that information. First, the script creates some common objects that you'll need to use, such as the WScript.Network and WScript.Shell objects. Next, it uses these objects to find out the user's name and domain information. Finally, using ADSI, the script returns information containing the Windows NT® group of the user. This information is used to determine the appropriate subroutine to call based on the user's group. A Select Case statement performs this feature.
      As mentioned, WSH comes with a very powerful object model. My logon script for users of my Windows NT group (named Chicago) makes use of the networking capabilities of WSH. It checks to see if a drive letter Z is already in use. If the drive is not already used, drive Z is set to

 \\VERNONH0\NETLOGON
using the format \\server\share.
      To break down the logon script example and help explain it, I've cut out some of the subroutines and functions. You can just place the following snippet back into the <script> block in Figure 1.

 sub Chicagologon
     if checkNetworkMapping("z:", "\\VERNONH0\NETLOGON") = false then
         mapNetwork "z:", "\\VERNONH0\NETLOGON "
     end if
 end sub
The checkNetworkMapping function enumerates through the various drive letters to determine whether the drive letter is already in use (see Figure 2). It returns true or false based on the availability of this drive letter. If it is true, then it calls the mapNetwork subroutine to perform the map. This subroutine uses the built-in MapNetworkDrive method of WSH to map the network share to the drive letter.
      Administrators may want some more detailed information to go beyond setting up network shares and user environments. They want to know more in-depth information about the computer, such as environment variables, computer configuration, hardware devices, and so on. Using only the WSH object model, the following code will show you how you can display some environment and registry information about your computer:

 sub Adminslogon
      Wscript.Echo _
        "—This will return some basic environment properties about the computer."
 ReturnENV
 Wscript.Echo
     regProxy
     Wscript.Echo
     'the following two lines require a server, username, and password for the 
     'function.
     Wscript.Echo "The IP addresses for this computer are: " & GetIPAddress _ 
         ("vernonh0", "administrator", "p-word")
     Wscript.Echo "The total RAM available to this machine is: " & GetRAM _
         ("vernonh0", "administrator", "p-word")
 end sub
Later, I'll show you how you can return more extended information with WMI, such as returning the IP address or total RAM of your computer.
      So far, I've used the WSH network object to help set up a network share. With the WSH shell object you can do even more. The returnENV method returns some sample environment information about your computer. First, you need to bind wshProcEnv to the process environment. Once you are bound to the process environment, you can return data such as the NUMBER_OF_PROCESSORS or PATH of the current machine configuration. Here are a few sample items that you can gather from the processor environment.

 sub returnENV()
     set wshShell = Wscript.CreateObject("WScript.Shell")
     set wshProcEnv = wshShell.environment("process")
 
     WScript.Echo ("NUMBER_OF_PROCESSORS: " & wshProcEnv _ 
         ("NUMBER_OF_PROCESSORS"))
     WScript.Echo
     WScript.Echo ("PROCESSOR_IDENTIFIER: " & wshProcEnv _
         ("PROCESSOR_IDENTIFIER"))
     WScript.Echo
     WScript.Echo ("OS: " & wshProcEnv ("OS"))
     WScript.Echo
     WScript.Echo ("PATH: " & wshProcEnv ("PATH"))
     WScript.Echo
     WScript.Echo ("WINDIR: " & wshProcEnv ("WINDIR"))
     WScript.Echo
 end sub
      Most people cringe when they hear talk about the registry, and justifiably so; tampering with the registry can really mess up your day. For those expert users who need to get in there, WSH provides an easy way to manipulate your registry. With the regRead, regWrite, and regDelete methods, you can manipulate to your heart's desire. All you have to do is point to the correct key to read, write, or delete.
      Now I'll set up the proxy server settings. I can return the current information stored in the registry key located at HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer using the regRead method. Then, using regWrite, I can overwrite that value with the name of my proxy server, MYPROXY:80. Finally, I'll make sure that I've written the information correctly by returning the value stored at that location, again with regRead.

 sub regProxy
     prefix = _
         "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\"
 
     WScript.Echo "Old ProxyServer settings: " & wshShell.regRead(prefix & _
         "ProxyServer")
     wshShell.regWrite prefix & "ProxyServer", "MYPROXY:80"
     WScript.Echo  "New ProxyServer settings: " & wshShell.regRead(prefix & _
         "ProxyServer")
 end sub
      You can gather lots of interesting information with WMI. The function GetIPAddress uses WMI to determine all IP addresses of the machine. I won't get into the details of WMI here, but basically the GetObject command grabs the WMI management object. This object contains a method, ExecQuery, which takes a string argument that describes the IP address. This returns a collection of all the IP addresses for a machine.
      GetRAM is very similar to GetIPAddress except that the string requested is different. As with the previous function, ExecQuery acts on the bounded WMI service object. Figure 3 shows implementations of GetIPAddress and GetRAM.
      To complete the logon script, save the code to logon.wsf (or some other name, if you prefer). You should put this in your Windows \\server\NETLOGON share. This is the directory that Windows NT will use to look for files such as logon scripts. Note that servers other than Windows 2000 may not execute files other than command and batch files. In this case, you should write a simple logon.bat file that calls

 cscript.exe logon.wsf
cscript.exe is the WSH executable for Windows-based console applications.
      Alternatively, it might be wise to change the two WMI functions found in Figure 3 to Windows Script Components. The advantage is that you can encapsulate all this functionality into a neat COM component that is modular and ready for reuse in multiple application settings.

WSH and ADSI
      Now that you have a logon script, what are you going to do with it? Imagine that you have to set up 5000 of your company's user accounts by the end of the week! Well, this is no problem because I am going to show you how to create a Windows NT group and user accounts, and then add them to the defined groups. Finally, I'll link and tie this all back to the previous section on user logon scripts.
      If you take a look at the Windows NT namespace of your server, you will notice several preset Windows NT groups such as Administrators and Domain Users. Creating your own Windows NT group on your server or domain is easy. All you have to do is specify the Windows NT computer where you'd like to create your group and the group name. The GetObject call binds you to the object that contains the information about your server. The next lines just create the group and set the description property. An important line of code is SetInfo, which saves the information to the server. The following code creates a group called Chicago with the description "Chicagoland office team" on the server vernonh0:


 sub CreateGroup (ServerName, GroupName, GroupDesc)
     on error resume next
     err.clear
 
     set objServer = GetObject("WinNT://" & ServerName)
     set objGroup = objServer.Create("group", GroupName)
     objGroup.Description = GroupDesc
     objGroup.SetInfo
 
     if err <> 0 then 
         WScript.Echo "Unable to create group" & GroupName
     Else
         Wscript.Echo "Finished creating group: " & GroupName
     end if
 end sub
 
 CreateGroup "vernonh0", "chicago", "Chicagoland office team"
If you wanted to create a domain group instead of a server group, you would just substitute DomainName for ServerName. You would also request to bind to the domain object instead of the server.
      Now that you have your first group, let's create some users. The code is actually very similar to the code that created the group. As before, you must bind to your computer or domain object with GetObject. Afterward, the code simply creates the user and sets some information such as fullname and password (users can change this when they log in or at a later date). The code in Figure 4 creates three users and sets their password, fullname, and logon script description properties. To find the logon script, Windows will default to looking at the \\server\NETLOGON path.
      Now you are ready to add your users to your Windows NT groups. For kicks, let's add two users to the Chicago group and one to the administrators group.

 sub AddUser (server, group, user)
     on error resume next
     err.clear
 
     set objGroup = GetObject("WinNT://" & server & "/" & group)
     objGroup.Add "WinNT://" & server & "/" & user
 
     if err <> 0 then 
         WScript.Echo "Unable to add" & user & " to group " & group
     Else
         Wscript.Echo "Finished adding " & user & " to group " & group
     end if
 end sub
 
 AddUser "vernonh0", "Chicago", "KenT"
 AddUser "vernonh0", "Chicago", "MariaL"
 AddUser "vernonh0", "administrators", "VinceH"
Conclusion
      This is just the tip of the iceberg for what you can do with WSH using WMI and ADSI. Windows Script Host lets you write language-independent scripts using its own object model or borrowed ones. So be creative; there are so many ways you can use WSH to accomplish your tedious and repetitive network administration tasks.


From the November 1999 issue of Microsoft Internet Developer.