windows & .net magazine's guide to automating administrative tasks with vbscript

52
W i n d o w s & . N E T M a g a z i n e s Guide to Automating Administrative Tasks with VBScript Don Baker, Don Jones, Lary Lai, Dick Lewis, Mike Otey, John Savill, Bob Wells

Upload: dwight66

Post on 10-Apr-2015

1.219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Wi n

d ow s amp N E T Mag

az

ine

rsquos

Guide to AutomatingAdministrative Tasks

with

VBScript

Don Baker Don Jones Lary Lai Dick Lewis Mike Otey John Savill Bob Wells

Employee

A Division of Penton Media

Windows amp NET Magazinersquos Guide to Automating Administrative Tasks

with VBScript

By Don Baker Don Jones Larry Lai Mike Otey John Savill Bob Wells

Copyright 2002Windows amp NET Magazine

All rights reserved No part of this book may be reproduced inany form by an electronic or mechanical means (includingphotocopying recording or information storage and retrieval)without permission in writing from the publisher

It is the readerrsquos responsibility to ensure procedures andtechniques used from this book are accurate and appropriate for the userrsquos installation No warranty is implied or expressed

About the AuthorsDon Baker (dbakerinternosiscom) is a consulting engineer with Internosis an e-business consul-tancy in Arlington Virginia He is an MCSE and an MCP and specializes in Systems ManagementServer and automated software deployment

Don Jones (httpwwwbraincorenet) is a founding partner of BrainCoreNet He is the author ofApplication Center 2000 Configuration and Administration (Hungry Minds)

Michael Otey (mikeotecacom) is senior technical editor for Windows amp NET Magazine andpresident of TECA a software-development and consulting company in Portland Oregon He iscoauthor of SQL Server 2000 Developerrsquos Guide (OsborneMcGraw-Hill)

John Savill (johnsavilltechcom) is a qualified consultant in England and an MCSE He is theauthor of The Windows NT and Windows 2000 Answer Book (Addison Wesley)

Bob Wells (bobwellswinnetmagcom) is a contributing editor for Windows amp NET Magazine Heis a programming writer at Microsoft where he is contributing to a new System AdministrationScripting Guide that Microsoft will include in its next Windows Server resource kit

Table of Contents

Chapter 1 Scripting 101 Declaring and Initializing Variables 1VBScript Basics 1Declaration and Initializing 4

VBScript Directives 4VBScript Variables 6Variable Initialization 6Constant Definitions 6

Demovbs End 7

Chapter 2 Scripting 101 Working with Objects 9Objects 9Objects vs Utilities 9What Is an Object 11Creating Objects 11

CreateObject 12GetObject 14

Chapter 3 VBScript Techniques 17Chapter 4 Scripting Command-Line Switches 21

Adding Flexibility with Switches 21Handling Omitted Switches 23

Chapter 5 Adding Users in Bulk 25Getting Started 25Writing the Script 27The Work Begins 29Do It with a Script 31

Chapter 6 VBScript to Generate a List of User Last Logon Times for a Domain 33Chapter 7 VBScript to Datastamp Log Files 35Chapter 8 Simplify Win2K Desktop Deployment 37

The Deployment Environment 37Create a Hard Disk Image 37Write a FinalSetupvbs Script 38Prepare the Disk Image 42

Unattended 43GuiUnattended 43GuiRunOnce 44UserData 44Identification 44Networking 44

Clone the Master Image to a Workstation 45

iv

1

Chapter 1

Scripting 101 Declaring and Initializing Variables By Bob Wells

The structure of a script consists of three sections declarations and initializations the body of thescript and function and subroutine definitions In this chapter I examine the declaration and ini-tialization section in detail Before we start you need to know some VBScript basics to ease yourtransition to Windows Script Host (WSH)

VBScript BasicsAs with any other programming or scripting language VBScript has some general ground rulesthat apply to every script At first glance these rules might not appear to be significant butknowing these language tidbits can often shave a few minutes off a frustrating debugging exercise

The first ground rule is that VBScript isnrsquot case-sensitive For example declaring a variable asstrTempFile and later referencing it as STRtEMPfILE is perfectly legal Likewise VBScript statementsfunction names and subroutine names are case-insensitive Despite this flexibility I encourage youto pick a case variation that suits your needs and stick with it

Although VBScript is case-insensitive some situations (eg comparing two string values)require you to be case-conscious You also need to be case-conscious when you use Active Direc-tory Service Interfaces (ADSI) namespace identifiers (eg LDAP to specify Lightweight DirectoryAccess Protocol WinNT to specify Windows NT NDS to specify NetWare 4x NWCOMPAT tospecify NetWare 3x) You must key ADSI namespace identifiers according to the ADSI specifica-tion or a runtime error will occur when your script attempts to bind to an ADSI namespace (Formore information about ADSI namespace usage read the Active Directory Programmerrsquos Guideavailable at httpmsdnmicrosoftcomlibrarydefaultaspurl=libraryen-usnetdiradusing_active_directoryasp

The second VBScript rule is that you can use either an apostrophe (lsquo) or a Rem statement toinclude comments in a script I use both styles in Listing 1rsquos demovbs script You can insert com-ments on a separate line or at the end of a line of code but you canrsquot insert comments at the endof a code line that contains a line-continuation marker (_) (To download an executable version ofListing 1 go to httpwwwwinnetmagcomfiles55055505zip)

The third rule is that VBScript doesnrsquot care about extra white space Adding extra spaces orblank lines can often improve the codersquos readability VBScript ignores the blank lines and the extraspaces between the variable name and the assignment operator (=)

The fourth rule is that although VBScript doesnrsquot impose a maximum line length breaking longlines into multiple short lines can improve the readability of a script In VBScript you can use theline-continuation marker to let a statement or line of code span multiple lines I often use the line-continuation marker when I initialize dynamic arrays (eg at callout A in Listing 1) or to pass a

long string to WScriptrsquos Echo method (WScriptEcho) which I demonstrate several times in the bodyof the demovbs script When you use the line-continuation marker you need to include one spaceimmediately before the underscore or you will encounter an error with some statement types

On the flip side of rule 4 is the fifth VBScript ground rule which lets one line of code containmultiple statements In VBScript you can use a colon () to separate multiple statements within aline of code In the code line

Dim strText strText = ldquoWSH ROCKSrdquo WScriptEcho strText

statement 1 is Dim strText statement 2 is strText = ldquoWSH ROCKSrdquo and statement 3 is WScriptEchostrText Although VBScript supports this capability I generally donrsquot use it

The sixth VBScript rule is that you must terminate each line of VBScript code with a new-linecharacter Pressing Enter automatically inserts the new-line character VBScript doesnrsquot use the vis-ible line terminator () that JScript and Perl use

The seventh and final ground rule I want to establish governs VBScript identifiers (eg vari-ables constants function names subroutine names) Identifiers canrsquot exceed 255 characters inlength and must begin with an uppercase or lowercase letter of the alphabet

Listing 1 Demovbs

rsquo lsquo demovbslsquo lsquo Declaration and Initialization Sectionlsquo Rem Script Directives Option ExplicitOn Error Resume Next

Rem Variable Declarations Dim objFileSystem objShell objLogFile objTempFileDim arrStrings intReturnCodeDim strBuffer strLogFile strTempFile

Rem Constant Definitions Const OpenFileForReading = 1

Rem Variable Initialization intReturnCode = 0strBuffer = ldquordquostrLogFile = ldquocrdquo amp Split(WScriptScriptName ldquordquo)(0) amp ldquologrdquostrTempFile = ldquoctemptxtrdquoarrStrings = Array(ldquoabcdefghijklmnopqrstuvwxyzrdquo _ AldquoABCDEFGHIJKLMNOPQRSTUVWXYZrdquo _ldquothe quick brown fox jumps over the lazy dogs backrdquo)

lsquo Script Body Sectionlsquo lsquo Using If-Then-End If to demonstrate the On Error Resume Next statement BIf ErrNumber ThenWScriptEcho ldquoBobrsquos Friendly Error Messagerdquo amp vbNewLine amp _ldquoError Number ldquo amp ErrNumber amp vbNewLine amp _ldquoError Description ldquo amp ErrDescriptionErrClear

End If

lsquo Create scripting runtime FileSystemObjectlsquo Create TextStream object for scriptrsquos log filelsquo Write starting line to log file

Continued

2 Guide to VBScripting

Listing 1 continuedSet objFileSystem = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set objLogFile = objFileSystemCreateTextFile(strLogFile TRUE)objLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Startedrdquo)

lsquo Create WSH Shell objectlsquo Run external command redirecting commands output to temporary filelsquo Check for error condition and write appropriate message to log fileSet objShell = WScriptCreateObject(ldquoWScriptShellrdquo)intReturnCode = objShellRun(ldquocmd C ipconfigexe gtrdquo amp strTempFile 0 TRUE)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoRun completed successfullyrdquo)

End If

lsquo Create TextStream object to read in ctemptxt file which the run command createdlsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Check for error and write appropriate message to log filelsquo Close TextStream objectSet objTempFile = objFileSystemOpenTextFile(strTempFile OpenFileForReading)strBuffer = objTempFileReadAllIf ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoOpen and read ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End IfobjTempFileClose

lsquo Display the buffer contents that are the redirected result of the runlsquo commandWScriptEcho strBuffer

lsquo Delete ctemptxt filelsquo Check for error and write appropriate message to log fileobjFileSystemDeleteFile(strTempFile)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoDelete ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End If

lsquo Write closing line to log file and close log fileobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Finishedrdquo)objLogFileClose

lsquo Create TextStream object to read in log filelsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Close TextStream objectSet objLogFile = objFileSystemOpenTextFile(strLogFile OpenFileForReading)strBuffer = objLogFileReadAllobjLogFileClose

lsquo Display the bufferrsquos content which is the log file in this caseWScriptEcho strBuffer

lsquo Delete the log file release object references and exit scriptobjFileSystemDeleteFile(strLogFile)Set objShell = NothingSet objFileSystem = NothingWScriptQuit(0)lsquo lsquo demovbs end

Chapter 1 Scripting 101 Declaring and Initializing Variables 3

Declaration and InitializationThe primary elements that make up declaration and initialization are script directives variable dec-larations variable initialization and constant definitions All these elements (with the possibleexception of initialization) are optional However using these language features can help you pro-duce scripts that are easier to debug and maintain

VBScript DirectivesVBScript includes two directives or statements that significantly affect the runtime behavior of scriptsThe two directives are the Option Explicit statement and the On Error Resume Next statement

The Option Explicit statement requires that you declare (ie define) all script variables via aVBScript Dim statement before you use the variables in an expression When you use OptionExplicit the declaration requirement applies throughout the entire script including variables in themain body of the script and variables in user-defined functions and subroutines You must includethe Option Explicit statement before any other statements in your script Therefore you alwaysfind Option Explicit at the top of scripts that use it The benefit of using Option Explicit is that anerror occurs whenever the VBScript interpreter encounters an undefined variable during script exe-cution Using Option Explicit helps you isolate typographical mistakes and variables with incorrectscopes (a scope defines the visibility of a variable to other parts of the script such as functions andsubroutines)

The On Error Resume Next statement controls how a script notifies you when a script encoun-ters a runtime error When a script runtime error occurs and the script doesnrsquot use the On ErrorResume Next statement WSH displays a dialog box containing the execution error information andaborts the script Figure 1 shows an example WSH Script Execution Error dialog box Including anOn Error Resume Next statement in a script effectively tells VBScript to continue execution despitea runtime error VBScriptrsquos built-in Err object is set with the corresponding error information andthe script continues The On Error Resume Next statement lets you trap errors and respond to themprogrammatically You can choose to display a friendly descriptive message or write the errorinformation to a log file Figure 2 shows an example customized error dialog box

Using On Error Resume Next to help trap errors is important Suppose I comment out (ieadd Rem to the beginning of) the line that declares variable intReturnCode at the beginning ofdemovbs

Rem Dim arrStrings intReturnCode

If I execute this modified script the script will run to completion but it might not produce thedesired result The script wonrsquot display the standard WSH Script Execution Error message on theconsole instead the script will produce Figure 2rsquos custom error dialog box which states that ascript variable is undefined The If-Then-End If statement at callout B in Listing 1 acts as a rudi-mentary error-handling routine that echos the contents of the VBScript Err objectrsquos Number andDescription properties After you click OK to acknowledge the error dialog box the script con-tinues because the On Error Resume Next directive tells the script to proceed despite the error (IfI commented out the On Error Resume Next directive and ran the script again Figure 1rsquos WSHScript Execution Error dialog box would display More important the script would abort as soon asI clicked OK in Figure 1rsquos dialog box Irsquod have no control over the remainder of the script The

4 Guide to VBScripting

only benefit of not using On Error Resume Next is that the error information in the WSH ScriptExecution Error dialog box can be more descriptive than the information in the Err objectrsquosDescription property Figure 1 not only includes the name of the undefined variable it also pro-vides the specific line number for the error In Figure 2 the error description simply states that thescript tried to use an undefined variable)

Figure 1Example WSH Script Execution Error dialog box

Figure 2A customized error dialog box

Why does an error occur In demovbs I initialize intReturnCode to 0 in line 19 of the script afew lines before callout A But because I specified the Option Explicit directive at the start of thescript and commented out intReturnCodersquos declaration statement an error occurs when the scripttries to execute the line that initializes the undeclared intReturnCode to 0 I can eliminate this errorand other potential variable declaration errors by removing the Option Explicit statement How-ever a better way to fix the problem is to define the undeclared variable (in this case remove theRem from the declaration statement)

Dim arrStrings intReturnCode

Chapter 1 Scripting 101 Declaring and Initializing Variables 5

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 2: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

A Division of Penton Media

Windows amp NET Magazinersquos Guide to Automating Administrative Tasks

with VBScript

By Don Baker Don Jones Larry Lai Mike Otey John Savill Bob Wells

Copyright 2002Windows amp NET Magazine

All rights reserved No part of this book may be reproduced inany form by an electronic or mechanical means (includingphotocopying recording or information storage and retrieval)without permission in writing from the publisher

It is the readerrsquos responsibility to ensure procedures andtechniques used from this book are accurate and appropriate for the userrsquos installation No warranty is implied or expressed

About the AuthorsDon Baker (dbakerinternosiscom) is a consulting engineer with Internosis an e-business consul-tancy in Arlington Virginia He is an MCSE and an MCP and specializes in Systems ManagementServer and automated software deployment

Don Jones (httpwwwbraincorenet) is a founding partner of BrainCoreNet He is the author ofApplication Center 2000 Configuration and Administration (Hungry Minds)

Michael Otey (mikeotecacom) is senior technical editor for Windows amp NET Magazine andpresident of TECA a software-development and consulting company in Portland Oregon He iscoauthor of SQL Server 2000 Developerrsquos Guide (OsborneMcGraw-Hill)

John Savill (johnsavilltechcom) is a qualified consultant in England and an MCSE He is theauthor of The Windows NT and Windows 2000 Answer Book (Addison Wesley)

Bob Wells (bobwellswinnetmagcom) is a contributing editor for Windows amp NET Magazine Heis a programming writer at Microsoft where he is contributing to a new System AdministrationScripting Guide that Microsoft will include in its next Windows Server resource kit

Table of Contents

Chapter 1 Scripting 101 Declaring and Initializing Variables 1VBScript Basics 1Declaration and Initializing 4

VBScript Directives 4VBScript Variables 6Variable Initialization 6Constant Definitions 6

Demovbs End 7

Chapter 2 Scripting 101 Working with Objects 9Objects 9Objects vs Utilities 9What Is an Object 11Creating Objects 11

CreateObject 12GetObject 14

Chapter 3 VBScript Techniques 17Chapter 4 Scripting Command-Line Switches 21

Adding Flexibility with Switches 21Handling Omitted Switches 23

Chapter 5 Adding Users in Bulk 25Getting Started 25Writing the Script 27The Work Begins 29Do It with a Script 31

Chapter 6 VBScript to Generate a List of User Last Logon Times for a Domain 33Chapter 7 VBScript to Datastamp Log Files 35Chapter 8 Simplify Win2K Desktop Deployment 37

The Deployment Environment 37Create a Hard Disk Image 37Write a FinalSetupvbs Script 38Prepare the Disk Image 42

Unattended 43GuiUnattended 43GuiRunOnce 44UserData 44Identification 44Networking 44

Clone the Master Image to a Workstation 45

iv

1

Chapter 1

Scripting 101 Declaring and Initializing Variables By Bob Wells

The structure of a script consists of three sections declarations and initializations the body of thescript and function and subroutine definitions In this chapter I examine the declaration and ini-tialization section in detail Before we start you need to know some VBScript basics to ease yourtransition to Windows Script Host (WSH)

VBScript BasicsAs with any other programming or scripting language VBScript has some general ground rulesthat apply to every script At first glance these rules might not appear to be significant butknowing these language tidbits can often shave a few minutes off a frustrating debugging exercise

The first ground rule is that VBScript isnrsquot case-sensitive For example declaring a variable asstrTempFile and later referencing it as STRtEMPfILE is perfectly legal Likewise VBScript statementsfunction names and subroutine names are case-insensitive Despite this flexibility I encourage youto pick a case variation that suits your needs and stick with it

Although VBScript is case-insensitive some situations (eg comparing two string values)require you to be case-conscious You also need to be case-conscious when you use Active Direc-tory Service Interfaces (ADSI) namespace identifiers (eg LDAP to specify Lightweight DirectoryAccess Protocol WinNT to specify Windows NT NDS to specify NetWare 4x NWCOMPAT tospecify NetWare 3x) You must key ADSI namespace identifiers according to the ADSI specifica-tion or a runtime error will occur when your script attempts to bind to an ADSI namespace (Formore information about ADSI namespace usage read the Active Directory Programmerrsquos Guideavailable at httpmsdnmicrosoftcomlibrarydefaultaspurl=libraryen-usnetdiradusing_active_directoryasp

The second VBScript rule is that you can use either an apostrophe (lsquo) or a Rem statement toinclude comments in a script I use both styles in Listing 1rsquos demovbs script You can insert com-ments on a separate line or at the end of a line of code but you canrsquot insert comments at the endof a code line that contains a line-continuation marker (_) (To download an executable version ofListing 1 go to httpwwwwinnetmagcomfiles55055505zip)

The third rule is that VBScript doesnrsquot care about extra white space Adding extra spaces orblank lines can often improve the codersquos readability VBScript ignores the blank lines and the extraspaces between the variable name and the assignment operator (=)

The fourth rule is that although VBScript doesnrsquot impose a maximum line length breaking longlines into multiple short lines can improve the readability of a script In VBScript you can use theline-continuation marker to let a statement or line of code span multiple lines I often use the line-continuation marker when I initialize dynamic arrays (eg at callout A in Listing 1) or to pass a

long string to WScriptrsquos Echo method (WScriptEcho) which I demonstrate several times in the bodyof the demovbs script When you use the line-continuation marker you need to include one spaceimmediately before the underscore or you will encounter an error with some statement types

On the flip side of rule 4 is the fifth VBScript ground rule which lets one line of code containmultiple statements In VBScript you can use a colon () to separate multiple statements within aline of code In the code line

Dim strText strText = ldquoWSH ROCKSrdquo WScriptEcho strText

statement 1 is Dim strText statement 2 is strText = ldquoWSH ROCKSrdquo and statement 3 is WScriptEchostrText Although VBScript supports this capability I generally donrsquot use it

The sixth VBScript rule is that you must terminate each line of VBScript code with a new-linecharacter Pressing Enter automatically inserts the new-line character VBScript doesnrsquot use the vis-ible line terminator () that JScript and Perl use

The seventh and final ground rule I want to establish governs VBScript identifiers (eg vari-ables constants function names subroutine names) Identifiers canrsquot exceed 255 characters inlength and must begin with an uppercase or lowercase letter of the alphabet

Listing 1 Demovbs

rsquo lsquo demovbslsquo lsquo Declaration and Initialization Sectionlsquo Rem Script Directives Option ExplicitOn Error Resume Next

Rem Variable Declarations Dim objFileSystem objShell objLogFile objTempFileDim arrStrings intReturnCodeDim strBuffer strLogFile strTempFile

Rem Constant Definitions Const OpenFileForReading = 1

Rem Variable Initialization intReturnCode = 0strBuffer = ldquordquostrLogFile = ldquocrdquo amp Split(WScriptScriptName ldquordquo)(0) amp ldquologrdquostrTempFile = ldquoctemptxtrdquoarrStrings = Array(ldquoabcdefghijklmnopqrstuvwxyzrdquo _ AldquoABCDEFGHIJKLMNOPQRSTUVWXYZrdquo _ldquothe quick brown fox jumps over the lazy dogs backrdquo)

lsquo Script Body Sectionlsquo lsquo Using If-Then-End If to demonstrate the On Error Resume Next statement BIf ErrNumber ThenWScriptEcho ldquoBobrsquos Friendly Error Messagerdquo amp vbNewLine amp _ldquoError Number ldquo amp ErrNumber amp vbNewLine amp _ldquoError Description ldquo amp ErrDescriptionErrClear

End If

lsquo Create scripting runtime FileSystemObjectlsquo Create TextStream object for scriptrsquos log filelsquo Write starting line to log file

Continued

2 Guide to VBScripting

Listing 1 continuedSet objFileSystem = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set objLogFile = objFileSystemCreateTextFile(strLogFile TRUE)objLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Startedrdquo)

lsquo Create WSH Shell objectlsquo Run external command redirecting commands output to temporary filelsquo Check for error condition and write appropriate message to log fileSet objShell = WScriptCreateObject(ldquoWScriptShellrdquo)intReturnCode = objShellRun(ldquocmd C ipconfigexe gtrdquo amp strTempFile 0 TRUE)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoRun completed successfullyrdquo)

End If

lsquo Create TextStream object to read in ctemptxt file which the run command createdlsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Check for error and write appropriate message to log filelsquo Close TextStream objectSet objTempFile = objFileSystemOpenTextFile(strTempFile OpenFileForReading)strBuffer = objTempFileReadAllIf ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoOpen and read ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End IfobjTempFileClose

lsquo Display the buffer contents that are the redirected result of the runlsquo commandWScriptEcho strBuffer

lsquo Delete ctemptxt filelsquo Check for error and write appropriate message to log fileobjFileSystemDeleteFile(strTempFile)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoDelete ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End If

lsquo Write closing line to log file and close log fileobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Finishedrdquo)objLogFileClose

lsquo Create TextStream object to read in log filelsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Close TextStream objectSet objLogFile = objFileSystemOpenTextFile(strLogFile OpenFileForReading)strBuffer = objLogFileReadAllobjLogFileClose

lsquo Display the bufferrsquos content which is the log file in this caseWScriptEcho strBuffer

lsquo Delete the log file release object references and exit scriptobjFileSystemDeleteFile(strLogFile)Set objShell = NothingSet objFileSystem = NothingWScriptQuit(0)lsquo lsquo demovbs end

Chapter 1 Scripting 101 Declaring and Initializing Variables 3

Declaration and InitializationThe primary elements that make up declaration and initialization are script directives variable dec-larations variable initialization and constant definitions All these elements (with the possibleexception of initialization) are optional However using these language features can help you pro-duce scripts that are easier to debug and maintain

VBScript DirectivesVBScript includes two directives or statements that significantly affect the runtime behavior of scriptsThe two directives are the Option Explicit statement and the On Error Resume Next statement

The Option Explicit statement requires that you declare (ie define) all script variables via aVBScript Dim statement before you use the variables in an expression When you use OptionExplicit the declaration requirement applies throughout the entire script including variables in themain body of the script and variables in user-defined functions and subroutines You must includethe Option Explicit statement before any other statements in your script Therefore you alwaysfind Option Explicit at the top of scripts that use it The benefit of using Option Explicit is that anerror occurs whenever the VBScript interpreter encounters an undefined variable during script exe-cution Using Option Explicit helps you isolate typographical mistakes and variables with incorrectscopes (a scope defines the visibility of a variable to other parts of the script such as functions andsubroutines)

The On Error Resume Next statement controls how a script notifies you when a script encoun-ters a runtime error When a script runtime error occurs and the script doesnrsquot use the On ErrorResume Next statement WSH displays a dialog box containing the execution error information andaborts the script Figure 1 shows an example WSH Script Execution Error dialog box Including anOn Error Resume Next statement in a script effectively tells VBScript to continue execution despitea runtime error VBScriptrsquos built-in Err object is set with the corresponding error information andthe script continues The On Error Resume Next statement lets you trap errors and respond to themprogrammatically You can choose to display a friendly descriptive message or write the errorinformation to a log file Figure 2 shows an example customized error dialog box

Using On Error Resume Next to help trap errors is important Suppose I comment out (ieadd Rem to the beginning of) the line that declares variable intReturnCode at the beginning ofdemovbs

Rem Dim arrStrings intReturnCode

If I execute this modified script the script will run to completion but it might not produce thedesired result The script wonrsquot display the standard WSH Script Execution Error message on theconsole instead the script will produce Figure 2rsquos custom error dialog box which states that ascript variable is undefined The If-Then-End If statement at callout B in Listing 1 acts as a rudi-mentary error-handling routine that echos the contents of the VBScript Err objectrsquos Number andDescription properties After you click OK to acknowledge the error dialog box the script con-tinues because the On Error Resume Next directive tells the script to proceed despite the error (IfI commented out the On Error Resume Next directive and ran the script again Figure 1rsquos WSHScript Execution Error dialog box would display More important the script would abort as soon asI clicked OK in Figure 1rsquos dialog box Irsquod have no control over the remainder of the script The

4 Guide to VBScripting

only benefit of not using On Error Resume Next is that the error information in the WSH ScriptExecution Error dialog box can be more descriptive than the information in the Err objectrsquosDescription property Figure 1 not only includes the name of the undefined variable it also pro-vides the specific line number for the error In Figure 2 the error description simply states that thescript tried to use an undefined variable)

Figure 1Example WSH Script Execution Error dialog box

Figure 2A customized error dialog box

Why does an error occur In demovbs I initialize intReturnCode to 0 in line 19 of the script afew lines before callout A But because I specified the Option Explicit directive at the start of thescript and commented out intReturnCodersquos declaration statement an error occurs when the scripttries to execute the line that initializes the undeclared intReturnCode to 0 I can eliminate this errorand other potential variable declaration errors by removing the Option Explicit statement How-ever a better way to fix the problem is to define the undeclared variable (in this case remove theRem from the declaration statement)

Dim arrStrings intReturnCode

Chapter 1 Scripting 101 Declaring and Initializing Variables 5

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 3: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Copyright 2002Windows amp NET Magazine

All rights reserved No part of this book may be reproduced inany form by an electronic or mechanical means (includingphotocopying recording or information storage and retrieval)without permission in writing from the publisher

It is the readerrsquos responsibility to ensure procedures andtechniques used from this book are accurate and appropriate for the userrsquos installation No warranty is implied or expressed

About the AuthorsDon Baker (dbakerinternosiscom) is a consulting engineer with Internosis an e-business consul-tancy in Arlington Virginia He is an MCSE and an MCP and specializes in Systems ManagementServer and automated software deployment

Don Jones (httpwwwbraincorenet) is a founding partner of BrainCoreNet He is the author ofApplication Center 2000 Configuration and Administration (Hungry Minds)

Michael Otey (mikeotecacom) is senior technical editor for Windows amp NET Magazine andpresident of TECA a software-development and consulting company in Portland Oregon He iscoauthor of SQL Server 2000 Developerrsquos Guide (OsborneMcGraw-Hill)

John Savill (johnsavilltechcom) is a qualified consultant in England and an MCSE He is theauthor of The Windows NT and Windows 2000 Answer Book (Addison Wesley)

Bob Wells (bobwellswinnetmagcom) is a contributing editor for Windows amp NET Magazine Heis a programming writer at Microsoft where he is contributing to a new System AdministrationScripting Guide that Microsoft will include in its next Windows Server resource kit

Table of Contents

Chapter 1 Scripting 101 Declaring and Initializing Variables 1VBScript Basics 1Declaration and Initializing 4

VBScript Directives 4VBScript Variables 6Variable Initialization 6Constant Definitions 6

Demovbs End 7

Chapter 2 Scripting 101 Working with Objects 9Objects 9Objects vs Utilities 9What Is an Object 11Creating Objects 11

CreateObject 12GetObject 14

Chapter 3 VBScript Techniques 17Chapter 4 Scripting Command-Line Switches 21

Adding Flexibility with Switches 21Handling Omitted Switches 23

Chapter 5 Adding Users in Bulk 25Getting Started 25Writing the Script 27The Work Begins 29Do It with a Script 31

Chapter 6 VBScript to Generate a List of User Last Logon Times for a Domain 33Chapter 7 VBScript to Datastamp Log Files 35Chapter 8 Simplify Win2K Desktop Deployment 37

The Deployment Environment 37Create a Hard Disk Image 37Write a FinalSetupvbs Script 38Prepare the Disk Image 42

Unattended 43GuiUnattended 43GuiRunOnce 44UserData 44Identification 44Networking 44

Clone the Master Image to a Workstation 45

iv

1

Chapter 1

Scripting 101 Declaring and Initializing Variables By Bob Wells

The structure of a script consists of three sections declarations and initializations the body of thescript and function and subroutine definitions In this chapter I examine the declaration and ini-tialization section in detail Before we start you need to know some VBScript basics to ease yourtransition to Windows Script Host (WSH)

VBScript BasicsAs with any other programming or scripting language VBScript has some general ground rulesthat apply to every script At first glance these rules might not appear to be significant butknowing these language tidbits can often shave a few minutes off a frustrating debugging exercise

The first ground rule is that VBScript isnrsquot case-sensitive For example declaring a variable asstrTempFile and later referencing it as STRtEMPfILE is perfectly legal Likewise VBScript statementsfunction names and subroutine names are case-insensitive Despite this flexibility I encourage youto pick a case variation that suits your needs and stick with it

Although VBScript is case-insensitive some situations (eg comparing two string values)require you to be case-conscious You also need to be case-conscious when you use Active Direc-tory Service Interfaces (ADSI) namespace identifiers (eg LDAP to specify Lightweight DirectoryAccess Protocol WinNT to specify Windows NT NDS to specify NetWare 4x NWCOMPAT tospecify NetWare 3x) You must key ADSI namespace identifiers according to the ADSI specifica-tion or a runtime error will occur when your script attempts to bind to an ADSI namespace (Formore information about ADSI namespace usage read the Active Directory Programmerrsquos Guideavailable at httpmsdnmicrosoftcomlibrarydefaultaspurl=libraryen-usnetdiradusing_active_directoryasp

The second VBScript rule is that you can use either an apostrophe (lsquo) or a Rem statement toinclude comments in a script I use both styles in Listing 1rsquos demovbs script You can insert com-ments on a separate line or at the end of a line of code but you canrsquot insert comments at the endof a code line that contains a line-continuation marker (_) (To download an executable version ofListing 1 go to httpwwwwinnetmagcomfiles55055505zip)

The third rule is that VBScript doesnrsquot care about extra white space Adding extra spaces orblank lines can often improve the codersquos readability VBScript ignores the blank lines and the extraspaces between the variable name and the assignment operator (=)

The fourth rule is that although VBScript doesnrsquot impose a maximum line length breaking longlines into multiple short lines can improve the readability of a script In VBScript you can use theline-continuation marker to let a statement or line of code span multiple lines I often use the line-continuation marker when I initialize dynamic arrays (eg at callout A in Listing 1) or to pass a

long string to WScriptrsquos Echo method (WScriptEcho) which I demonstrate several times in the bodyof the demovbs script When you use the line-continuation marker you need to include one spaceimmediately before the underscore or you will encounter an error with some statement types

On the flip side of rule 4 is the fifth VBScript ground rule which lets one line of code containmultiple statements In VBScript you can use a colon () to separate multiple statements within aline of code In the code line

Dim strText strText = ldquoWSH ROCKSrdquo WScriptEcho strText

statement 1 is Dim strText statement 2 is strText = ldquoWSH ROCKSrdquo and statement 3 is WScriptEchostrText Although VBScript supports this capability I generally donrsquot use it

The sixth VBScript rule is that you must terminate each line of VBScript code with a new-linecharacter Pressing Enter automatically inserts the new-line character VBScript doesnrsquot use the vis-ible line terminator () that JScript and Perl use

The seventh and final ground rule I want to establish governs VBScript identifiers (eg vari-ables constants function names subroutine names) Identifiers canrsquot exceed 255 characters inlength and must begin with an uppercase or lowercase letter of the alphabet

Listing 1 Demovbs

rsquo lsquo demovbslsquo lsquo Declaration and Initialization Sectionlsquo Rem Script Directives Option ExplicitOn Error Resume Next

Rem Variable Declarations Dim objFileSystem objShell objLogFile objTempFileDim arrStrings intReturnCodeDim strBuffer strLogFile strTempFile

Rem Constant Definitions Const OpenFileForReading = 1

Rem Variable Initialization intReturnCode = 0strBuffer = ldquordquostrLogFile = ldquocrdquo amp Split(WScriptScriptName ldquordquo)(0) amp ldquologrdquostrTempFile = ldquoctemptxtrdquoarrStrings = Array(ldquoabcdefghijklmnopqrstuvwxyzrdquo _ AldquoABCDEFGHIJKLMNOPQRSTUVWXYZrdquo _ldquothe quick brown fox jumps over the lazy dogs backrdquo)

lsquo Script Body Sectionlsquo lsquo Using If-Then-End If to demonstrate the On Error Resume Next statement BIf ErrNumber ThenWScriptEcho ldquoBobrsquos Friendly Error Messagerdquo amp vbNewLine amp _ldquoError Number ldquo amp ErrNumber amp vbNewLine amp _ldquoError Description ldquo amp ErrDescriptionErrClear

End If

lsquo Create scripting runtime FileSystemObjectlsquo Create TextStream object for scriptrsquos log filelsquo Write starting line to log file

Continued

2 Guide to VBScripting

Listing 1 continuedSet objFileSystem = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set objLogFile = objFileSystemCreateTextFile(strLogFile TRUE)objLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Startedrdquo)

lsquo Create WSH Shell objectlsquo Run external command redirecting commands output to temporary filelsquo Check for error condition and write appropriate message to log fileSet objShell = WScriptCreateObject(ldquoWScriptShellrdquo)intReturnCode = objShellRun(ldquocmd C ipconfigexe gtrdquo amp strTempFile 0 TRUE)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoRun completed successfullyrdquo)

End If

lsquo Create TextStream object to read in ctemptxt file which the run command createdlsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Check for error and write appropriate message to log filelsquo Close TextStream objectSet objTempFile = objFileSystemOpenTextFile(strTempFile OpenFileForReading)strBuffer = objTempFileReadAllIf ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoOpen and read ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End IfobjTempFileClose

lsquo Display the buffer contents that are the redirected result of the runlsquo commandWScriptEcho strBuffer

lsquo Delete ctemptxt filelsquo Check for error and write appropriate message to log fileobjFileSystemDeleteFile(strTempFile)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoDelete ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End If

lsquo Write closing line to log file and close log fileobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Finishedrdquo)objLogFileClose

lsquo Create TextStream object to read in log filelsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Close TextStream objectSet objLogFile = objFileSystemOpenTextFile(strLogFile OpenFileForReading)strBuffer = objLogFileReadAllobjLogFileClose

lsquo Display the bufferrsquos content which is the log file in this caseWScriptEcho strBuffer

lsquo Delete the log file release object references and exit scriptobjFileSystemDeleteFile(strLogFile)Set objShell = NothingSet objFileSystem = NothingWScriptQuit(0)lsquo lsquo demovbs end

Chapter 1 Scripting 101 Declaring and Initializing Variables 3

Declaration and InitializationThe primary elements that make up declaration and initialization are script directives variable dec-larations variable initialization and constant definitions All these elements (with the possibleexception of initialization) are optional However using these language features can help you pro-duce scripts that are easier to debug and maintain

VBScript DirectivesVBScript includes two directives or statements that significantly affect the runtime behavior of scriptsThe two directives are the Option Explicit statement and the On Error Resume Next statement

The Option Explicit statement requires that you declare (ie define) all script variables via aVBScript Dim statement before you use the variables in an expression When you use OptionExplicit the declaration requirement applies throughout the entire script including variables in themain body of the script and variables in user-defined functions and subroutines You must includethe Option Explicit statement before any other statements in your script Therefore you alwaysfind Option Explicit at the top of scripts that use it The benefit of using Option Explicit is that anerror occurs whenever the VBScript interpreter encounters an undefined variable during script exe-cution Using Option Explicit helps you isolate typographical mistakes and variables with incorrectscopes (a scope defines the visibility of a variable to other parts of the script such as functions andsubroutines)

The On Error Resume Next statement controls how a script notifies you when a script encoun-ters a runtime error When a script runtime error occurs and the script doesnrsquot use the On ErrorResume Next statement WSH displays a dialog box containing the execution error information andaborts the script Figure 1 shows an example WSH Script Execution Error dialog box Including anOn Error Resume Next statement in a script effectively tells VBScript to continue execution despitea runtime error VBScriptrsquos built-in Err object is set with the corresponding error information andthe script continues The On Error Resume Next statement lets you trap errors and respond to themprogrammatically You can choose to display a friendly descriptive message or write the errorinformation to a log file Figure 2 shows an example customized error dialog box

Using On Error Resume Next to help trap errors is important Suppose I comment out (ieadd Rem to the beginning of) the line that declares variable intReturnCode at the beginning ofdemovbs

Rem Dim arrStrings intReturnCode

If I execute this modified script the script will run to completion but it might not produce thedesired result The script wonrsquot display the standard WSH Script Execution Error message on theconsole instead the script will produce Figure 2rsquos custom error dialog box which states that ascript variable is undefined The If-Then-End If statement at callout B in Listing 1 acts as a rudi-mentary error-handling routine that echos the contents of the VBScript Err objectrsquos Number andDescription properties After you click OK to acknowledge the error dialog box the script con-tinues because the On Error Resume Next directive tells the script to proceed despite the error (IfI commented out the On Error Resume Next directive and ran the script again Figure 1rsquos WSHScript Execution Error dialog box would display More important the script would abort as soon asI clicked OK in Figure 1rsquos dialog box Irsquod have no control over the remainder of the script The

4 Guide to VBScripting

only benefit of not using On Error Resume Next is that the error information in the WSH ScriptExecution Error dialog box can be more descriptive than the information in the Err objectrsquosDescription property Figure 1 not only includes the name of the undefined variable it also pro-vides the specific line number for the error In Figure 2 the error description simply states that thescript tried to use an undefined variable)

Figure 1Example WSH Script Execution Error dialog box

Figure 2A customized error dialog box

Why does an error occur In demovbs I initialize intReturnCode to 0 in line 19 of the script afew lines before callout A But because I specified the Option Explicit directive at the start of thescript and commented out intReturnCodersquos declaration statement an error occurs when the scripttries to execute the line that initializes the undeclared intReturnCode to 0 I can eliminate this errorand other potential variable declaration errors by removing the Option Explicit statement How-ever a better way to fix the problem is to define the undeclared variable (in this case remove theRem from the declaration statement)

Dim arrStrings intReturnCode

Chapter 1 Scripting 101 Declaring and Initializing Variables 5

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 4: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

About the AuthorsDon Baker (dbakerinternosiscom) is a consulting engineer with Internosis an e-business consul-tancy in Arlington Virginia He is an MCSE and an MCP and specializes in Systems ManagementServer and automated software deployment

Don Jones (httpwwwbraincorenet) is a founding partner of BrainCoreNet He is the author ofApplication Center 2000 Configuration and Administration (Hungry Minds)

Michael Otey (mikeotecacom) is senior technical editor for Windows amp NET Magazine andpresident of TECA a software-development and consulting company in Portland Oregon He iscoauthor of SQL Server 2000 Developerrsquos Guide (OsborneMcGraw-Hill)

John Savill (johnsavilltechcom) is a qualified consultant in England and an MCSE He is theauthor of The Windows NT and Windows 2000 Answer Book (Addison Wesley)

Bob Wells (bobwellswinnetmagcom) is a contributing editor for Windows amp NET Magazine Heis a programming writer at Microsoft where he is contributing to a new System AdministrationScripting Guide that Microsoft will include in its next Windows Server resource kit

Table of Contents

Chapter 1 Scripting 101 Declaring and Initializing Variables 1VBScript Basics 1Declaration and Initializing 4

VBScript Directives 4VBScript Variables 6Variable Initialization 6Constant Definitions 6

Demovbs End 7

Chapter 2 Scripting 101 Working with Objects 9Objects 9Objects vs Utilities 9What Is an Object 11Creating Objects 11

CreateObject 12GetObject 14

Chapter 3 VBScript Techniques 17Chapter 4 Scripting Command-Line Switches 21

Adding Flexibility with Switches 21Handling Omitted Switches 23

Chapter 5 Adding Users in Bulk 25Getting Started 25Writing the Script 27The Work Begins 29Do It with a Script 31

Chapter 6 VBScript to Generate a List of User Last Logon Times for a Domain 33Chapter 7 VBScript to Datastamp Log Files 35Chapter 8 Simplify Win2K Desktop Deployment 37

The Deployment Environment 37Create a Hard Disk Image 37Write a FinalSetupvbs Script 38Prepare the Disk Image 42

Unattended 43GuiUnattended 43GuiRunOnce 44UserData 44Identification 44Networking 44

Clone the Master Image to a Workstation 45

iv

1

Chapter 1

Scripting 101 Declaring and Initializing Variables By Bob Wells

The structure of a script consists of three sections declarations and initializations the body of thescript and function and subroutine definitions In this chapter I examine the declaration and ini-tialization section in detail Before we start you need to know some VBScript basics to ease yourtransition to Windows Script Host (WSH)

VBScript BasicsAs with any other programming or scripting language VBScript has some general ground rulesthat apply to every script At first glance these rules might not appear to be significant butknowing these language tidbits can often shave a few minutes off a frustrating debugging exercise

The first ground rule is that VBScript isnrsquot case-sensitive For example declaring a variable asstrTempFile and later referencing it as STRtEMPfILE is perfectly legal Likewise VBScript statementsfunction names and subroutine names are case-insensitive Despite this flexibility I encourage youto pick a case variation that suits your needs and stick with it

Although VBScript is case-insensitive some situations (eg comparing two string values)require you to be case-conscious You also need to be case-conscious when you use Active Direc-tory Service Interfaces (ADSI) namespace identifiers (eg LDAP to specify Lightweight DirectoryAccess Protocol WinNT to specify Windows NT NDS to specify NetWare 4x NWCOMPAT tospecify NetWare 3x) You must key ADSI namespace identifiers according to the ADSI specifica-tion or a runtime error will occur when your script attempts to bind to an ADSI namespace (Formore information about ADSI namespace usage read the Active Directory Programmerrsquos Guideavailable at httpmsdnmicrosoftcomlibrarydefaultaspurl=libraryen-usnetdiradusing_active_directoryasp

The second VBScript rule is that you can use either an apostrophe (lsquo) or a Rem statement toinclude comments in a script I use both styles in Listing 1rsquos demovbs script You can insert com-ments on a separate line or at the end of a line of code but you canrsquot insert comments at the endof a code line that contains a line-continuation marker (_) (To download an executable version ofListing 1 go to httpwwwwinnetmagcomfiles55055505zip)

The third rule is that VBScript doesnrsquot care about extra white space Adding extra spaces orblank lines can often improve the codersquos readability VBScript ignores the blank lines and the extraspaces between the variable name and the assignment operator (=)

The fourth rule is that although VBScript doesnrsquot impose a maximum line length breaking longlines into multiple short lines can improve the readability of a script In VBScript you can use theline-continuation marker to let a statement or line of code span multiple lines I often use the line-continuation marker when I initialize dynamic arrays (eg at callout A in Listing 1) or to pass a

long string to WScriptrsquos Echo method (WScriptEcho) which I demonstrate several times in the bodyof the demovbs script When you use the line-continuation marker you need to include one spaceimmediately before the underscore or you will encounter an error with some statement types

On the flip side of rule 4 is the fifth VBScript ground rule which lets one line of code containmultiple statements In VBScript you can use a colon () to separate multiple statements within aline of code In the code line

Dim strText strText = ldquoWSH ROCKSrdquo WScriptEcho strText

statement 1 is Dim strText statement 2 is strText = ldquoWSH ROCKSrdquo and statement 3 is WScriptEchostrText Although VBScript supports this capability I generally donrsquot use it

The sixth VBScript rule is that you must terminate each line of VBScript code with a new-linecharacter Pressing Enter automatically inserts the new-line character VBScript doesnrsquot use the vis-ible line terminator () that JScript and Perl use

The seventh and final ground rule I want to establish governs VBScript identifiers (eg vari-ables constants function names subroutine names) Identifiers canrsquot exceed 255 characters inlength and must begin with an uppercase or lowercase letter of the alphabet

Listing 1 Demovbs

rsquo lsquo demovbslsquo lsquo Declaration and Initialization Sectionlsquo Rem Script Directives Option ExplicitOn Error Resume Next

Rem Variable Declarations Dim objFileSystem objShell objLogFile objTempFileDim arrStrings intReturnCodeDim strBuffer strLogFile strTempFile

Rem Constant Definitions Const OpenFileForReading = 1

Rem Variable Initialization intReturnCode = 0strBuffer = ldquordquostrLogFile = ldquocrdquo amp Split(WScriptScriptName ldquordquo)(0) amp ldquologrdquostrTempFile = ldquoctemptxtrdquoarrStrings = Array(ldquoabcdefghijklmnopqrstuvwxyzrdquo _ AldquoABCDEFGHIJKLMNOPQRSTUVWXYZrdquo _ldquothe quick brown fox jumps over the lazy dogs backrdquo)

lsquo Script Body Sectionlsquo lsquo Using If-Then-End If to demonstrate the On Error Resume Next statement BIf ErrNumber ThenWScriptEcho ldquoBobrsquos Friendly Error Messagerdquo amp vbNewLine amp _ldquoError Number ldquo amp ErrNumber amp vbNewLine amp _ldquoError Description ldquo amp ErrDescriptionErrClear

End If

lsquo Create scripting runtime FileSystemObjectlsquo Create TextStream object for scriptrsquos log filelsquo Write starting line to log file

Continued

2 Guide to VBScripting

Listing 1 continuedSet objFileSystem = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set objLogFile = objFileSystemCreateTextFile(strLogFile TRUE)objLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Startedrdquo)

lsquo Create WSH Shell objectlsquo Run external command redirecting commands output to temporary filelsquo Check for error condition and write appropriate message to log fileSet objShell = WScriptCreateObject(ldquoWScriptShellrdquo)intReturnCode = objShellRun(ldquocmd C ipconfigexe gtrdquo amp strTempFile 0 TRUE)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoRun completed successfullyrdquo)

End If

lsquo Create TextStream object to read in ctemptxt file which the run command createdlsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Check for error and write appropriate message to log filelsquo Close TextStream objectSet objTempFile = objFileSystemOpenTextFile(strTempFile OpenFileForReading)strBuffer = objTempFileReadAllIf ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoOpen and read ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End IfobjTempFileClose

lsquo Display the buffer contents that are the redirected result of the runlsquo commandWScriptEcho strBuffer

lsquo Delete ctemptxt filelsquo Check for error and write appropriate message to log fileobjFileSystemDeleteFile(strTempFile)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoDelete ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End If

lsquo Write closing line to log file and close log fileobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Finishedrdquo)objLogFileClose

lsquo Create TextStream object to read in log filelsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Close TextStream objectSet objLogFile = objFileSystemOpenTextFile(strLogFile OpenFileForReading)strBuffer = objLogFileReadAllobjLogFileClose

lsquo Display the bufferrsquos content which is the log file in this caseWScriptEcho strBuffer

lsquo Delete the log file release object references and exit scriptobjFileSystemDeleteFile(strLogFile)Set objShell = NothingSet objFileSystem = NothingWScriptQuit(0)lsquo lsquo demovbs end

Chapter 1 Scripting 101 Declaring and Initializing Variables 3

Declaration and InitializationThe primary elements that make up declaration and initialization are script directives variable dec-larations variable initialization and constant definitions All these elements (with the possibleexception of initialization) are optional However using these language features can help you pro-duce scripts that are easier to debug and maintain

VBScript DirectivesVBScript includes two directives or statements that significantly affect the runtime behavior of scriptsThe two directives are the Option Explicit statement and the On Error Resume Next statement

The Option Explicit statement requires that you declare (ie define) all script variables via aVBScript Dim statement before you use the variables in an expression When you use OptionExplicit the declaration requirement applies throughout the entire script including variables in themain body of the script and variables in user-defined functions and subroutines You must includethe Option Explicit statement before any other statements in your script Therefore you alwaysfind Option Explicit at the top of scripts that use it The benefit of using Option Explicit is that anerror occurs whenever the VBScript interpreter encounters an undefined variable during script exe-cution Using Option Explicit helps you isolate typographical mistakes and variables with incorrectscopes (a scope defines the visibility of a variable to other parts of the script such as functions andsubroutines)

The On Error Resume Next statement controls how a script notifies you when a script encoun-ters a runtime error When a script runtime error occurs and the script doesnrsquot use the On ErrorResume Next statement WSH displays a dialog box containing the execution error information andaborts the script Figure 1 shows an example WSH Script Execution Error dialog box Including anOn Error Resume Next statement in a script effectively tells VBScript to continue execution despitea runtime error VBScriptrsquos built-in Err object is set with the corresponding error information andthe script continues The On Error Resume Next statement lets you trap errors and respond to themprogrammatically You can choose to display a friendly descriptive message or write the errorinformation to a log file Figure 2 shows an example customized error dialog box

Using On Error Resume Next to help trap errors is important Suppose I comment out (ieadd Rem to the beginning of) the line that declares variable intReturnCode at the beginning ofdemovbs

Rem Dim arrStrings intReturnCode

If I execute this modified script the script will run to completion but it might not produce thedesired result The script wonrsquot display the standard WSH Script Execution Error message on theconsole instead the script will produce Figure 2rsquos custom error dialog box which states that ascript variable is undefined The If-Then-End If statement at callout B in Listing 1 acts as a rudi-mentary error-handling routine that echos the contents of the VBScript Err objectrsquos Number andDescription properties After you click OK to acknowledge the error dialog box the script con-tinues because the On Error Resume Next directive tells the script to proceed despite the error (IfI commented out the On Error Resume Next directive and ran the script again Figure 1rsquos WSHScript Execution Error dialog box would display More important the script would abort as soon asI clicked OK in Figure 1rsquos dialog box Irsquod have no control over the remainder of the script The

4 Guide to VBScripting

only benefit of not using On Error Resume Next is that the error information in the WSH ScriptExecution Error dialog box can be more descriptive than the information in the Err objectrsquosDescription property Figure 1 not only includes the name of the undefined variable it also pro-vides the specific line number for the error In Figure 2 the error description simply states that thescript tried to use an undefined variable)

Figure 1Example WSH Script Execution Error dialog box

Figure 2A customized error dialog box

Why does an error occur In demovbs I initialize intReturnCode to 0 in line 19 of the script afew lines before callout A But because I specified the Option Explicit directive at the start of thescript and commented out intReturnCodersquos declaration statement an error occurs when the scripttries to execute the line that initializes the undeclared intReturnCode to 0 I can eliminate this errorand other potential variable declaration errors by removing the Option Explicit statement How-ever a better way to fix the problem is to define the undeclared variable (in this case remove theRem from the declaration statement)

Dim arrStrings intReturnCode

Chapter 1 Scripting 101 Declaring and Initializing Variables 5

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 5: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Table of Contents

Chapter 1 Scripting 101 Declaring and Initializing Variables 1VBScript Basics 1Declaration and Initializing 4

VBScript Directives 4VBScript Variables 6Variable Initialization 6Constant Definitions 6

Demovbs End 7

Chapter 2 Scripting 101 Working with Objects 9Objects 9Objects vs Utilities 9What Is an Object 11Creating Objects 11

CreateObject 12GetObject 14

Chapter 3 VBScript Techniques 17Chapter 4 Scripting Command-Line Switches 21

Adding Flexibility with Switches 21Handling Omitted Switches 23

Chapter 5 Adding Users in Bulk 25Getting Started 25Writing the Script 27The Work Begins 29Do It with a Script 31

Chapter 6 VBScript to Generate a List of User Last Logon Times for a Domain 33Chapter 7 VBScript to Datastamp Log Files 35Chapter 8 Simplify Win2K Desktop Deployment 37

The Deployment Environment 37Create a Hard Disk Image 37Write a FinalSetupvbs Script 38Prepare the Disk Image 42

Unattended 43GuiUnattended 43GuiRunOnce 44UserData 44Identification 44Networking 44

Clone the Master Image to a Workstation 45

iv

1

Chapter 1

Scripting 101 Declaring and Initializing Variables By Bob Wells

The structure of a script consists of three sections declarations and initializations the body of thescript and function and subroutine definitions In this chapter I examine the declaration and ini-tialization section in detail Before we start you need to know some VBScript basics to ease yourtransition to Windows Script Host (WSH)

VBScript BasicsAs with any other programming or scripting language VBScript has some general ground rulesthat apply to every script At first glance these rules might not appear to be significant butknowing these language tidbits can often shave a few minutes off a frustrating debugging exercise

The first ground rule is that VBScript isnrsquot case-sensitive For example declaring a variable asstrTempFile and later referencing it as STRtEMPfILE is perfectly legal Likewise VBScript statementsfunction names and subroutine names are case-insensitive Despite this flexibility I encourage youto pick a case variation that suits your needs and stick with it

Although VBScript is case-insensitive some situations (eg comparing two string values)require you to be case-conscious You also need to be case-conscious when you use Active Direc-tory Service Interfaces (ADSI) namespace identifiers (eg LDAP to specify Lightweight DirectoryAccess Protocol WinNT to specify Windows NT NDS to specify NetWare 4x NWCOMPAT tospecify NetWare 3x) You must key ADSI namespace identifiers according to the ADSI specifica-tion or a runtime error will occur when your script attempts to bind to an ADSI namespace (Formore information about ADSI namespace usage read the Active Directory Programmerrsquos Guideavailable at httpmsdnmicrosoftcomlibrarydefaultaspurl=libraryen-usnetdiradusing_active_directoryasp

The second VBScript rule is that you can use either an apostrophe (lsquo) or a Rem statement toinclude comments in a script I use both styles in Listing 1rsquos demovbs script You can insert com-ments on a separate line or at the end of a line of code but you canrsquot insert comments at the endof a code line that contains a line-continuation marker (_) (To download an executable version ofListing 1 go to httpwwwwinnetmagcomfiles55055505zip)

The third rule is that VBScript doesnrsquot care about extra white space Adding extra spaces orblank lines can often improve the codersquos readability VBScript ignores the blank lines and the extraspaces between the variable name and the assignment operator (=)

The fourth rule is that although VBScript doesnrsquot impose a maximum line length breaking longlines into multiple short lines can improve the readability of a script In VBScript you can use theline-continuation marker to let a statement or line of code span multiple lines I often use the line-continuation marker when I initialize dynamic arrays (eg at callout A in Listing 1) or to pass a

long string to WScriptrsquos Echo method (WScriptEcho) which I demonstrate several times in the bodyof the demovbs script When you use the line-continuation marker you need to include one spaceimmediately before the underscore or you will encounter an error with some statement types

On the flip side of rule 4 is the fifth VBScript ground rule which lets one line of code containmultiple statements In VBScript you can use a colon () to separate multiple statements within aline of code In the code line

Dim strText strText = ldquoWSH ROCKSrdquo WScriptEcho strText

statement 1 is Dim strText statement 2 is strText = ldquoWSH ROCKSrdquo and statement 3 is WScriptEchostrText Although VBScript supports this capability I generally donrsquot use it

The sixth VBScript rule is that you must terminate each line of VBScript code with a new-linecharacter Pressing Enter automatically inserts the new-line character VBScript doesnrsquot use the vis-ible line terminator () that JScript and Perl use

The seventh and final ground rule I want to establish governs VBScript identifiers (eg vari-ables constants function names subroutine names) Identifiers canrsquot exceed 255 characters inlength and must begin with an uppercase or lowercase letter of the alphabet

Listing 1 Demovbs

rsquo lsquo demovbslsquo lsquo Declaration and Initialization Sectionlsquo Rem Script Directives Option ExplicitOn Error Resume Next

Rem Variable Declarations Dim objFileSystem objShell objLogFile objTempFileDim arrStrings intReturnCodeDim strBuffer strLogFile strTempFile

Rem Constant Definitions Const OpenFileForReading = 1

Rem Variable Initialization intReturnCode = 0strBuffer = ldquordquostrLogFile = ldquocrdquo amp Split(WScriptScriptName ldquordquo)(0) amp ldquologrdquostrTempFile = ldquoctemptxtrdquoarrStrings = Array(ldquoabcdefghijklmnopqrstuvwxyzrdquo _ AldquoABCDEFGHIJKLMNOPQRSTUVWXYZrdquo _ldquothe quick brown fox jumps over the lazy dogs backrdquo)

lsquo Script Body Sectionlsquo lsquo Using If-Then-End If to demonstrate the On Error Resume Next statement BIf ErrNumber ThenWScriptEcho ldquoBobrsquos Friendly Error Messagerdquo amp vbNewLine amp _ldquoError Number ldquo amp ErrNumber amp vbNewLine amp _ldquoError Description ldquo amp ErrDescriptionErrClear

End If

lsquo Create scripting runtime FileSystemObjectlsquo Create TextStream object for scriptrsquos log filelsquo Write starting line to log file

Continued

2 Guide to VBScripting

Listing 1 continuedSet objFileSystem = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set objLogFile = objFileSystemCreateTextFile(strLogFile TRUE)objLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Startedrdquo)

lsquo Create WSH Shell objectlsquo Run external command redirecting commands output to temporary filelsquo Check for error condition and write appropriate message to log fileSet objShell = WScriptCreateObject(ldquoWScriptShellrdquo)intReturnCode = objShellRun(ldquocmd C ipconfigexe gtrdquo amp strTempFile 0 TRUE)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoRun completed successfullyrdquo)

End If

lsquo Create TextStream object to read in ctemptxt file which the run command createdlsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Check for error and write appropriate message to log filelsquo Close TextStream objectSet objTempFile = objFileSystemOpenTextFile(strTempFile OpenFileForReading)strBuffer = objTempFileReadAllIf ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoOpen and read ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End IfobjTempFileClose

lsquo Display the buffer contents that are the redirected result of the runlsquo commandWScriptEcho strBuffer

lsquo Delete ctemptxt filelsquo Check for error and write appropriate message to log fileobjFileSystemDeleteFile(strTempFile)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoDelete ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End If

lsquo Write closing line to log file and close log fileobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Finishedrdquo)objLogFileClose

lsquo Create TextStream object to read in log filelsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Close TextStream objectSet objLogFile = objFileSystemOpenTextFile(strLogFile OpenFileForReading)strBuffer = objLogFileReadAllobjLogFileClose

lsquo Display the bufferrsquos content which is the log file in this caseWScriptEcho strBuffer

lsquo Delete the log file release object references and exit scriptobjFileSystemDeleteFile(strLogFile)Set objShell = NothingSet objFileSystem = NothingWScriptQuit(0)lsquo lsquo demovbs end

Chapter 1 Scripting 101 Declaring and Initializing Variables 3

Declaration and InitializationThe primary elements that make up declaration and initialization are script directives variable dec-larations variable initialization and constant definitions All these elements (with the possibleexception of initialization) are optional However using these language features can help you pro-duce scripts that are easier to debug and maintain

VBScript DirectivesVBScript includes two directives or statements that significantly affect the runtime behavior of scriptsThe two directives are the Option Explicit statement and the On Error Resume Next statement

The Option Explicit statement requires that you declare (ie define) all script variables via aVBScript Dim statement before you use the variables in an expression When you use OptionExplicit the declaration requirement applies throughout the entire script including variables in themain body of the script and variables in user-defined functions and subroutines You must includethe Option Explicit statement before any other statements in your script Therefore you alwaysfind Option Explicit at the top of scripts that use it The benefit of using Option Explicit is that anerror occurs whenever the VBScript interpreter encounters an undefined variable during script exe-cution Using Option Explicit helps you isolate typographical mistakes and variables with incorrectscopes (a scope defines the visibility of a variable to other parts of the script such as functions andsubroutines)

The On Error Resume Next statement controls how a script notifies you when a script encoun-ters a runtime error When a script runtime error occurs and the script doesnrsquot use the On ErrorResume Next statement WSH displays a dialog box containing the execution error information andaborts the script Figure 1 shows an example WSH Script Execution Error dialog box Including anOn Error Resume Next statement in a script effectively tells VBScript to continue execution despitea runtime error VBScriptrsquos built-in Err object is set with the corresponding error information andthe script continues The On Error Resume Next statement lets you trap errors and respond to themprogrammatically You can choose to display a friendly descriptive message or write the errorinformation to a log file Figure 2 shows an example customized error dialog box

Using On Error Resume Next to help trap errors is important Suppose I comment out (ieadd Rem to the beginning of) the line that declares variable intReturnCode at the beginning ofdemovbs

Rem Dim arrStrings intReturnCode

If I execute this modified script the script will run to completion but it might not produce thedesired result The script wonrsquot display the standard WSH Script Execution Error message on theconsole instead the script will produce Figure 2rsquos custom error dialog box which states that ascript variable is undefined The If-Then-End If statement at callout B in Listing 1 acts as a rudi-mentary error-handling routine that echos the contents of the VBScript Err objectrsquos Number andDescription properties After you click OK to acknowledge the error dialog box the script con-tinues because the On Error Resume Next directive tells the script to proceed despite the error (IfI commented out the On Error Resume Next directive and ran the script again Figure 1rsquos WSHScript Execution Error dialog box would display More important the script would abort as soon asI clicked OK in Figure 1rsquos dialog box Irsquod have no control over the remainder of the script The

4 Guide to VBScripting

only benefit of not using On Error Resume Next is that the error information in the WSH ScriptExecution Error dialog box can be more descriptive than the information in the Err objectrsquosDescription property Figure 1 not only includes the name of the undefined variable it also pro-vides the specific line number for the error In Figure 2 the error description simply states that thescript tried to use an undefined variable)

Figure 1Example WSH Script Execution Error dialog box

Figure 2A customized error dialog box

Why does an error occur In demovbs I initialize intReturnCode to 0 in line 19 of the script afew lines before callout A But because I specified the Option Explicit directive at the start of thescript and commented out intReturnCodersquos declaration statement an error occurs when the scripttries to execute the line that initializes the undeclared intReturnCode to 0 I can eliminate this errorand other potential variable declaration errors by removing the Option Explicit statement How-ever a better way to fix the problem is to define the undeclared variable (in this case remove theRem from the declaration statement)

Dim arrStrings intReturnCode

Chapter 1 Scripting 101 Declaring and Initializing Variables 5

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 6: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

1

Chapter 1

Scripting 101 Declaring and Initializing Variables By Bob Wells

The structure of a script consists of three sections declarations and initializations the body of thescript and function and subroutine definitions In this chapter I examine the declaration and ini-tialization section in detail Before we start you need to know some VBScript basics to ease yourtransition to Windows Script Host (WSH)

VBScript BasicsAs with any other programming or scripting language VBScript has some general ground rulesthat apply to every script At first glance these rules might not appear to be significant butknowing these language tidbits can often shave a few minutes off a frustrating debugging exercise

The first ground rule is that VBScript isnrsquot case-sensitive For example declaring a variable asstrTempFile and later referencing it as STRtEMPfILE is perfectly legal Likewise VBScript statementsfunction names and subroutine names are case-insensitive Despite this flexibility I encourage youto pick a case variation that suits your needs and stick with it

Although VBScript is case-insensitive some situations (eg comparing two string values)require you to be case-conscious You also need to be case-conscious when you use Active Direc-tory Service Interfaces (ADSI) namespace identifiers (eg LDAP to specify Lightweight DirectoryAccess Protocol WinNT to specify Windows NT NDS to specify NetWare 4x NWCOMPAT tospecify NetWare 3x) You must key ADSI namespace identifiers according to the ADSI specifica-tion or a runtime error will occur when your script attempts to bind to an ADSI namespace (Formore information about ADSI namespace usage read the Active Directory Programmerrsquos Guideavailable at httpmsdnmicrosoftcomlibrarydefaultaspurl=libraryen-usnetdiradusing_active_directoryasp

The second VBScript rule is that you can use either an apostrophe (lsquo) or a Rem statement toinclude comments in a script I use both styles in Listing 1rsquos demovbs script You can insert com-ments on a separate line or at the end of a line of code but you canrsquot insert comments at the endof a code line that contains a line-continuation marker (_) (To download an executable version ofListing 1 go to httpwwwwinnetmagcomfiles55055505zip)

The third rule is that VBScript doesnrsquot care about extra white space Adding extra spaces orblank lines can often improve the codersquos readability VBScript ignores the blank lines and the extraspaces between the variable name and the assignment operator (=)

The fourth rule is that although VBScript doesnrsquot impose a maximum line length breaking longlines into multiple short lines can improve the readability of a script In VBScript you can use theline-continuation marker to let a statement or line of code span multiple lines I often use the line-continuation marker when I initialize dynamic arrays (eg at callout A in Listing 1) or to pass a

long string to WScriptrsquos Echo method (WScriptEcho) which I demonstrate several times in the bodyof the demovbs script When you use the line-continuation marker you need to include one spaceimmediately before the underscore or you will encounter an error with some statement types

On the flip side of rule 4 is the fifth VBScript ground rule which lets one line of code containmultiple statements In VBScript you can use a colon () to separate multiple statements within aline of code In the code line

Dim strText strText = ldquoWSH ROCKSrdquo WScriptEcho strText

statement 1 is Dim strText statement 2 is strText = ldquoWSH ROCKSrdquo and statement 3 is WScriptEchostrText Although VBScript supports this capability I generally donrsquot use it

The sixth VBScript rule is that you must terminate each line of VBScript code with a new-linecharacter Pressing Enter automatically inserts the new-line character VBScript doesnrsquot use the vis-ible line terminator () that JScript and Perl use

The seventh and final ground rule I want to establish governs VBScript identifiers (eg vari-ables constants function names subroutine names) Identifiers canrsquot exceed 255 characters inlength and must begin with an uppercase or lowercase letter of the alphabet

Listing 1 Demovbs

rsquo lsquo demovbslsquo lsquo Declaration and Initialization Sectionlsquo Rem Script Directives Option ExplicitOn Error Resume Next

Rem Variable Declarations Dim objFileSystem objShell objLogFile objTempFileDim arrStrings intReturnCodeDim strBuffer strLogFile strTempFile

Rem Constant Definitions Const OpenFileForReading = 1

Rem Variable Initialization intReturnCode = 0strBuffer = ldquordquostrLogFile = ldquocrdquo amp Split(WScriptScriptName ldquordquo)(0) amp ldquologrdquostrTempFile = ldquoctemptxtrdquoarrStrings = Array(ldquoabcdefghijklmnopqrstuvwxyzrdquo _ AldquoABCDEFGHIJKLMNOPQRSTUVWXYZrdquo _ldquothe quick brown fox jumps over the lazy dogs backrdquo)

lsquo Script Body Sectionlsquo lsquo Using If-Then-End If to demonstrate the On Error Resume Next statement BIf ErrNumber ThenWScriptEcho ldquoBobrsquos Friendly Error Messagerdquo amp vbNewLine amp _ldquoError Number ldquo amp ErrNumber amp vbNewLine amp _ldquoError Description ldquo amp ErrDescriptionErrClear

End If

lsquo Create scripting runtime FileSystemObjectlsquo Create TextStream object for scriptrsquos log filelsquo Write starting line to log file

Continued

2 Guide to VBScripting

Listing 1 continuedSet objFileSystem = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set objLogFile = objFileSystemCreateTextFile(strLogFile TRUE)objLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Startedrdquo)

lsquo Create WSH Shell objectlsquo Run external command redirecting commands output to temporary filelsquo Check for error condition and write appropriate message to log fileSet objShell = WScriptCreateObject(ldquoWScriptShellrdquo)intReturnCode = objShellRun(ldquocmd C ipconfigexe gtrdquo amp strTempFile 0 TRUE)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoRun completed successfullyrdquo)

End If

lsquo Create TextStream object to read in ctemptxt file which the run command createdlsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Check for error and write appropriate message to log filelsquo Close TextStream objectSet objTempFile = objFileSystemOpenTextFile(strTempFile OpenFileForReading)strBuffer = objTempFileReadAllIf ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoOpen and read ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End IfobjTempFileClose

lsquo Display the buffer contents that are the redirected result of the runlsquo commandWScriptEcho strBuffer

lsquo Delete ctemptxt filelsquo Check for error and write appropriate message to log fileobjFileSystemDeleteFile(strTempFile)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoDelete ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End If

lsquo Write closing line to log file and close log fileobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Finishedrdquo)objLogFileClose

lsquo Create TextStream object to read in log filelsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Close TextStream objectSet objLogFile = objFileSystemOpenTextFile(strLogFile OpenFileForReading)strBuffer = objLogFileReadAllobjLogFileClose

lsquo Display the bufferrsquos content which is the log file in this caseWScriptEcho strBuffer

lsquo Delete the log file release object references and exit scriptobjFileSystemDeleteFile(strLogFile)Set objShell = NothingSet objFileSystem = NothingWScriptQuit(0)lsquo lsquo demovbs end

Chapter 1 Scripting 101 Declaring and Initializing Variables 3

Declaration and InitializationThe primary elements that make up declaration and initialization are script directives variable dec-larations variable initialization and constant definitions All these elements (with the possibleexception of initialization) are optional However using these language features can help you pro-duce scripts that are easier to debug and maintain

VBScript DirectivesVBScript includes two directives or statements that significantly affect the runtime behavior of scriptsThe two directives are the Option Explicit statement and the On Error Resume Next statement

The Option Explicit statement requires that you declare (ie define) all script variables via aVBScript Dim statement before you use the variables in an expression When you use OptionExplicit the declaration requirement applies throughout the entire script including variables in themain body of the script and variables in user-defined functions and subroutines You must includethe Option Explicit statement before any other statements in your script Therefore you alwaysfind Option Explicit at the top of scripts that use it The benefit of using Option Explicit is that anerror occurs whenever the VBScript interpreter encounters an undefined variable during script exe-cution Using Option Explicit helps you isolate typographical mistakes and variables with incorrectscopes (a scope defines the visibility of a variable to other parts of the script such as functions andsubroutines)

The On Error Resume Next statement controls how a script notifies you when a script encoun-ters a runtime error When a script runtime error occurs and the script doesnrsquot use the On ErrorResume Next statement WSH displays a dialog box containing the execution error information andaborts the script Figure 1 shows an example WSH Script Execution Error dialog box Including anOn Error Resume Next statement in a script effectively tells VBScript to continue execution despitea runtime error VBScriptrsquos built-in Err object is set with the corresponding error information andthe script continues The On Error Resume Next statement lets you trap errors and respond to themprogrammatically You can choose to display a friendly descriptive message or write the errorinformation to a log file Figure 2 shows an example customized error dialog box

Using On Error Resume Next to help trap errors is important Suppose I comment out (ieadd Rem to the beginning of) the line that declares variable intReturnCode at the beginning ofdemovbs

Rem Dim arrStrings intReturnCode

If I execute this modified script the script will run to completion but it might not produce thedesired result The script wonrsquot display the standard WSH Script Execution Error message on theconsole instead the script will produce Figure 2rsquos custom error dialog box which states that ascript variable is undefined The If-Then-End If statement at callout B in Listing 1 acts as a rudi-mentary error-handling routine that echos the contents of the VBScript Err objectrsquos Number andDescription properties After you click OK to acknowledge the error dialog box the script con-tinues because the On Error Resume Next directive tells the script to proceed despite the error (IfI commented out the On Error Resume Next directive and ran the script again Figure 1rsquos WSHScript Execution Error dialog box would display More important the script would abort as soon asI clicked OK in Figure 1rsquos dialog box Irsquod have no control over the remainder of the script The

4 Guide to VBScripting

only benefit of not using On Error Resume Next is that the error information in the WSH ScriptExecution Error dialog box can be more descriptive than the information in the Err objectrsquosDescription property Figure 1 not only includes the name of the undefined variable it also pro-vides the specific line number for the error In Figure 2 the error description simply states that thescript tried to use an undefined variable)

Figure 1Example WSH Script Execution Error dialog box

Figure 2A customized error dialog box

Why does an error occur In demovbs I initialize intReturnCode to 0 in line 19 of the script afew lines before callout A But because I specified the Option Explicit directive at the start of thescript and commented out intReturnCodersquos declaration statement an error occurs when the scripttries to execute the line that initializes the undeclared intReturnCode to 0 I can eliminate this errorand other potential variable declaration errors by removing the Option Explicit statement How-ever a better way to fix the problem is to define the undeclared variable (in this case remove theRem from the declaration statement)

Dim arrStrings intReturnCode

Chapter 1 Scripting 101 Declaring and Initializing Variables 5

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 7: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

long string to WScriptrsquos Echo method (WScriptEcho) which I demonstrate several times in the bodyof the demovbs script When you use the line-continuation marker you need to include one spaceimmediately before the underscore or you will encounter an error with some statement types

On the flip side of rule 4 is the fifth VBScript ground rule which lets one line of code containmultiple statements In VBScript you can use a colon () to separate multiple statements within aline of code In the code line

Dim strText strText = ldquoWSH ROCKSrdquo WScriptEcho strText

statement 1 is Dim strText statement 2 is strText = ldquoWSH ROCKSrdquo and statement 3 is WScriptEchostrText Although VBScript supports this capability I generally donrsquot use it

The sixth VBScript rule is that you must terminate each line of VBScript code with a new-linecharacter Pressing Enter automatically inserts the new-line character VBScript doesnrsquot use the vis-ible line terminator () that JScript and Perl use

The seventh and final ground rule I want to establish governs VBScript identifiers (eg vari-ables constants function names subroutine names) Identifiers canrsquot exceed 255 characters inlength and must begin with an uppercase or lowercase letter of the alphabet

Listing 1 Demovbs

rsquo lsquo demovbslsquo lsquo Declaration and Initialization Sectionlsquo Rem Script Directives Option ExplicitOn Error Resume Next

Rem Variable Declarations Dim objFileSystem objShell objLogFile objTempFileDim arrStrings intReturnCodeDim strBuffer strLogFile strTempFile

Rem Constant Definitions Const OpenFileForReading = 1

Rem Variable Initialization intReturnCode = 0strBuffer = ldquordquostrLogFile = ldquocrdquo amp Split(WScriptScriptName ldquordquo)(0) amp ldquologrdquostrTempFile = ldquoctemptxtrdquoarrStrings = Array(ldquoabcdefghijklmnopqrstuvwxyzrdquo _ AldquoABCDEFGHIJKLMNOPQRSTUVWXYZrdquo _ldquothe quick brown fox jumps over the lazy dogs backrdquo)

lsquo Script Body Sectionlsquo lsquo Using If-Then-End If to demonstrate the On Error Resume Next statement BIf ErrNumber ThenWScriptEcho ldquoBobrsquos Friendly Error Messagerdquo amp vbNewLine amp _ldquoError Number ldquo amp ErrNumber amp vbNewLine amp _ldquoError Description ldquo amp ErrDescriptionErrClear

End If

lsquo Create scripting runtime FileSystemObjectlsquo Create TextStream object for scriptrsquos log filelsquo Write starting line to log file

Continued

2 Guide to VBScripting

Listing 1 continuedSet objFileSystem = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set objLogFile = objFileSystemCreateTextFile(strLogFile TRUE)objLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Startedrdquo)

lsquo Create WSH Shell objectlsquo Run external command redirecting commands output to temporary filelsquo Check for error condition and write appropriate message to log fileSet objShell = WScriptCreateObject(ldquoWScriptShellrdquo)intReturnCode = objShellRun(ldquocmd C ipconfigexe gtrdquo amp strTempFile 0 TRUE)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoRun completed successfullyrdquo)

End If

lsquo Create TextStream object to read in ctemptxt file which the run command createdlsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Check for error and write appropriate message to log filelsquo Close TextStream objectSet objTempFile = objFileSystemOpenTextFile(strTempFile OpenFileForReading)strBuffer = objTempFileReadAllIf ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoOpen and read ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End IfobjTempFileClose

lsquo Display the buffer contents that are the redirected result of the runlsquo commandWScriptEcho strBuffer

lsquo Delete ctemptxt filelsquo Check for error and write appropriate message to log fileobjFileSystemDeleteFile(strTempFile)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoDelete ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End If

lsquo Write closing line to log file and close log fileobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Finishedrdquo)objLogFileClose

lsquo Create TextStream object to read in log filelsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Close TextStream objectSet objLogFile = objFileSystemOpenTextFile(strLogFile OpenFileForReading)strBuffer = objLogFileReadAllobjLogFileClose

lsquo Display the bufferrsquos content which is the log file in this caseWScriptEcho strBuffer

lsquo Delete the log file release object references and exit scriptobjFileSystemDeleteFile(strLogFile)Set objShell = NothingSet objFileSystem = NothingWScriptQuit(0)lsquo lsquo demovbs end

Chapter 1 Scripting 101 Declaring and Initializing Variables 3

Declaration and InitializationThe primary elements that make up declaration and initialization are script directives variable dec-larations variable initialization and constant definitions All these elements (with the possibleexception of initialization) are optional However using these language features can help you pro-duce scripts that are easier to debug and maintain

VBScript DirectivesVBScript includes two directives or statements that significantly affect the runtime behavior of scriptsThe two directives are the Option Explicit statement and the On Error Resume Next statement

The Option Explicit statement requires that you declare (ie define) all script variables via aVBScript Dim statement before you use the variables in an expression When you use OptionExplicit the declaration requirement applies throughout the entire script including variables in themain body of the script and variables in user-defined functions and subroutines You must includethe Option Explicit statement before any other statements in your script Therefore you alwaysfind Option Explicit at the top of scripts that use it The benefit of using Option Explicit is that anerror occurs whenever the VBScript interpreter encounters an undefined variable during script exe-cution Using Option Explicit helps you isolate typographical mistakes and variables with incorrectscopes (a scope defines the visibility of a variable to other parts of the script such as functions andsubroutines)

The On Error Resume Next statement controls how a script notifies you when a script encoun-ters a runtime error When a script runtime error occurs and the script doesnrsquot use the On ErrorResume Next statement WSH displays a dialog box containing the execution error information andaborts the script Figure 1 shows an example WSH Script Execution Error dialog box Including anOn Error Resume Next statement in a script effectively tells VBScript to continue execution despitea runtime error VBScriptrsquos built-in Err object is set with the corresponding error information andthe script continues The On Error Resume Next statement lets you trap errors and respond to themprogrammatically You can choose to display a friendly descriptive message or write the errorinformation to a log file Figure 2 shows an example customized error dialog box

Using On Error Resume Next to help trap errors is important Suppose I comment out (ieadd Rem to the beginning of) the line that declares variable intReturnCode at the beginning ofdemovbs

Rem Dim arrStrings intReturnCode

If I execute this modified script the script will run to completion but it might not produce thedesired result The script wonrsquot display the standard WSH Script Execution Error message on theconsole instead the script will produce Figure 2rsquos custom error dialog box which states that ascript variable is undefined The If-Then-End If statement at callout B in Listing 1 acts as a rudi-mentary error-handling routine that echos the contents of the VBScript Err objectrsquos Number andDescription properties After you click OK to acknowledge the error dialog box the script con-tinues because the On Error Resume Next directive tells the script to proceed despite the error (IfI commented out the On Error Resume Next directive and ran the script again Figure 1rsquos WSHScript Execution Error dialog box would display More important the script would abort as soon asI clicked OK in Figure 1rsquos dialog box Irsquod have no control over the remainder of the script The

4 Guide to VBScripting

only benefit of not using On Error Resume Next is that the error information in the WSH ScriptExecution Error dialog box can be more descriptive than the information in the Err objectrsquosDescription property Figure 1 not only includes the name of the undefined variable it also pro-vides the specific line number for the error In Figure 2 the error description simply states that thescript tried to use an undefined variable)

Figure 1Example WSH Script Execution Error dialog box

Figure 2A customized error dialog box

Why does an error occur In demovbs I initialize intReturnCode to 0 in line 19 of the script afew lines before callout A But because I specified the Option Explicit directive at the start of thescript and commented out intReturnCodersquos declaration statement an error occurs when the scripttries to execute the line that initializes the undeclared intReturnCode to 0 I can eliminate this errorand other potential variable declaration errors by removing the Option Explicit statement How-ever a better way to fix the problem is to define the undeclared variable (in this case remove theRem from the declaration statement)

Dim arrStrings intReturnCode

Chapter 1 Scripting 101 Declaring and Initializing Variables 5

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 8: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Listing 1 continuedSet objFileSystem = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set objLogFile = objFileSystemCreateTextFile(strLogFile TRUE)objLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Startedrdquo)

lsquo Create WSH Shell objectlsquo Run external command redirecting commands output to temporary filelsquo Check for error condition and write appropriate message to log fileSet objShell = WScriptCreateObject(ldquoWScriptShellrdquo)intReturnCode = objShellRun(ldquocmd C ipconfigexe gtrdquo amp strTempFile 0 TRUE)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoRun completed successfullyrdquo)

End If

lsquo Create TextStream object to read in ctemptxt file which the run command createdlsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Check for error and write appropriate message to log filelsquo Close TextStream objectSet objTempFile = objFileSystemOpenTextFile(strTempFile OpenFileForReading)strBuffer = objTempFileReadAllIf ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoOpen and read ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End IfobjTempFileClose

lsquo Display the buffer contents that are the redirected result of the runlsquo commandWScriptEcho strBuffer

lsquo Delete ctemptxt filelsquo Check for error and write appropriate message to log fileobjFileSystemDeleteFile(strTempFile)If ErrNumber ThenobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ErrNumber amp ldquo ldquo amp ErrDescription)ErrClear

ElseobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp ldquoDelete ldquo amp strTempFile amp _ldquo completed successfullyrdquo)

End If

lsquo Write closing line to log file and close log fileobjLogFileWriteLine(Now amp ldquordquo amp vbTab amp WScriptScriptFullName amp ldquo Finishedrdquo)objLogFileClose

lsquo Create TextStream object to read in log filelsquo Read entire file into buffer using the TextStream objects ReadAll methodlsquo Close TextStream objectSet objLogFile = objFileSystemOpenTextFile(strLogFile OpenFileForReading)strBuffer = objLogFileReadAllobjLogFileClose

lsquo Display the bufferrsquos content which is the log file in this caseWScriptEcho strBuffer

lsquo Delete the log file release object references and exit scriptobjFileSystemDeleteFile(strLogFile)Set objShell = NothingSet objFileSystem = NothingWScriptQuit(0)lsquo lsquo demovbs end

Chapter 1 Scripting 101 Declaring and Initializing Variables 3

Declaration and InitializationThe primary elements that make up declaration and initialization are script directives variable dec-larations variable initialization and constant definitions All these elements (with the possibleexception of initialization) are optional However using these language features can help you pro-duce scripts that are easier to debug and maintain

VBScript DirectivesVBScript includes two directives or statements that significantly affect the runtime behavior of scriptsThe two directives are the Option Explicit statement and the On Error Resume Next statement

The Option Explicit statement requires that you declare (ie define) all script variables via aVBScript Dim statement before you use the variables in an expression When you use OptionExplicit the declaration requirement applies throughout the entire script including variables in themain body of the script and variables in user-defined functions and subroutines You must includethe Option Explicit statement before any other statements in your script Therefore you alwaysfind Option Explicit at the top of scripts that use it The benefit of using Option Explicit is that anerror occurs whenever the VBScript interpreter encounters an undefined variable during script exe-cution Using Option Explicit helps you isolate typographical mistakes and variables with incorrectscopes (a scope defines the visibility of a variable to other parts of the script such as functions andsubroutines)

The On Error Resume Next statement controls how a script notifies you when a script encoun-ters a runtime error When a script runtime error occurs and the script doesnrsquot use the On ErrorResume Next statement WSH displays a dialog box containing the execution error information andaborts the script Figure 1 shows an example WSH Script Execution Error dialog box Including anOn Error Resume Next statement in a script effectively tells VBScript to continue execution despitea runtime error VBScriptrsquos built-in Err object is set with the corresponding error information andthe script continues The On Error Resume Next statement lets you trap errors and respond to themprogrammatically You can choose to display a friendly descriptive message or write the errorinformation to a log file Figure 2 shows an example customized error dialog box

Using On Error Resume Next to help trap errors is important Suppose I comment out (ieadd Rem to the beginning of) the line that declares variable intReturnCode at the beginning ofdemovbs

Rem Dim arrStrings intReturnCode

If I execute this modified script the script will run to completion but it might not produce thedesired result The script wonrsquot display the standard WSH Script Execution Error message on theconsole instead the script will produce Figure 2rsquos custom error dialog box which states that ascript variable is undefined The If-Then-End If statement at callout B in Listing 1 acts as a rudi-mentary error-handling routine that echos the contents of the VBScript Err objectrsquos Number andDescription properties After you click OK to acknowledge the error dialog box the script con-tinues because the On Error Resume Next directive tells the script to proceed despite the error (IfI commented out the On Error Resume Next directive and ran the script again Figure 1rsquos WSHScript Execution Error dialog box would display More important the script would abort as soon asI clicked OK in Figure 1rsquos dialog box Irsquod have no control over the remainder of the script The

4 Guide to VBScripting

only benefit of not using On Error Resume Next is that the error information in the WSH ScriptExecution Error dialog box can be more descriptive than the information in the Err objectrsquosDescription property Figure 1 not only includes the name of the undefined variable it also pro-vides the specific line number for the error In Figure 2 the error description simply states that thescript tried to use an undefined variable)

Figure 1Example WSH Script Execution Error dialog box

Figure 2A customized error dialog box

Why does an error occur In demovbs I initialize intReturnCode to 0 in line 19 of the script afew lines before callout A But because I specified the Option Explicit directive at the start of thescript and commented out intReturnCodersquos declaration statement an error occurs when the scripttries to execute the line that initializes the undeclared intReturnCode to 0 I can eliminate this errorand other potential variable declaration errors by removing the Option Explicit statement How-ever a better way to fix the problem is to define the undeclared variable (in this case remove theRem from the declaration statement)

Dim arrStrings intReturnCode

Chapter 1 Scripting 101 Declaring and Initializing Variables 5

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 9: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Declaration and InitializationThe primary elements that make up declaration and initialization are script directives variable dec-larations variable initialization and constant definitions All these elements (with the possibleexception of initialization) are optional However using these language features can help you pro-duce scripts that are easier to debug and maintain

VBScript DirectivesVBScript includes two directives or statements that significantly affect the runtime behavior of scriptsThe two directives are the Option Explicit statement and the On Error Resume Next statement

The Option Explicit statement requires that you declare (ie define) all script variables via aVBScript Dim statement before you use the variables in an expression When you use OptionExplicit the declaration requirement applies throughout the entire script including variables in themain body of the script and variables in user-defined functions and subroutines You must includethe Option Explicit statement before any other statements in your script Therefore you alwaysfind Option Explicit at the top of scripts that use it The benefit of using Option Explicit is that anerror occurs whenever the VBScript interpreter encounters an undefined variable during script exe-cution Using Option Explicit helps you isolate typographical mistakes and variables with incorrectscopes (a scope defines the visibility of a variable to other parts of the script such as functions andsubroutines)

The On Error Resume Next statement controls how a script notifies you when a script encoun-ters a runtime error When a script runtime error occurs and the script doesnrsquot use the On ErrorResume Next statement WSH displays a dialog box containing the execution error information andaborts the script Figure 1 shows an example WSH Script Execution Error dialog box Including anOn Error Resume Next statement in a script effectively tells VBScript to continue execution despitea runtime error VBScriptrsquos built-in Err object is set with the corresponding error information andthe script continues The On Error Resume Next statement lets you trap errors and respond to themprogrammatically You can choose to display a friendly descriptive message or write the errorinformation to a log file Figure 2 shows an example customized error dialog box

Using On Error Resume Next to help trap errors is important Suppose I comment out (ieadd Rem to the beginning of) the line that declares variable intReturnCode at the beginning ofdemovbs

Rem Dim arrStrings intReturnCode

If I execute this modified script the script will run to completion but it might not produce thedesired result The script wonrsquot display the standard WSH Script Execution Error message on theconsole instead the script will produce Figure 2rsquos custom error dialog box which states that ascript variable is undefined The If-Then-End If statement at callout B in Listing 1 acts as a rudi-mentary error-handling routine that echos the contents of the VBScript Err objectrsquos Number andDescription properties After you click OK to acknowledge the error dialog box the script con-tinues because the On Error Resume Next directive tells the script to proceed despite the error (IfI commented out the On Error Resume Next directive and ran the script again Figure 1rsquos WSHScript Execution Error dialog box would display More important the script would abort as soon asI clicked OK in Figure 1rsquos dialog box Irsquod have no control over the remainder of the script The

4 Guide to VBScripting

only benefit of not using On Error Resume Next is that the error information in the WSH ScriptExecution Error dialog box can be more descriptive than the information in the Err objectrsquosDescription property Figure 1 not only includes the name of the undefined variable it also pro-vides the specific line number for the error In Figure 2 the error description simply states that thescript tried to use an undefined variable)

Figure 1Example WSH Script Execution Error dialog box

Figure 2A customized error dialog box

Why does an error occur In demovbs I initialize intReturnCode to 0 in line 19 of the script afew lines before callout A But because I specified the Option Explicit directive at the start of thescript and commented out intReturnCodersquos declaration statement an error occurs when the scripttries to execute the line that initializes the undeclared intReturnCode to 0 I can eliminate this errorand other potential variable declaration errors by removing the Option Explicit statement How-ever a better way to fix the problem is to define the undeclared variable (in this case remove theRem from the declaration statement)

Dim arrStrings intReturnCode

Chapter 1 Scripting 101 Declaring and Initializing Variables 5

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 10: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

only benefit of not using On Error Resume Next is that the error information in the WSH ScriptExecution Error dialog box can be more descriptive than the information in the Err objectrsquosDescription property Figure 1 not only includes the name of the undefined variable it also pro-vides the specific line number for the error In Figure 2 the error description simply states that thescript tried to use an undefined variable)

Figure 1Example WSH Script Execution Error dialog box

Figure 2A customized error dialog box

Why does an error occur In demovbs I initialize intReturnCode to 0 in line 19 of the script afew lines before callout A But because I specified the Option Explicit directive at the start of thescript and commented out intReturnCodersquos declaration statement an error occurs when the scripttries to execute the line that initializes the undeclared intReturnCode to 0 I can eliminate this errorand other potential variable declaration errors by removing the Option Explicit statement How-ever a better way to fix the problem is to define the undeclared variable (in this case remove theRem from the declaration statement)

Dim arrStrings intReturnCode

Chapter 1 Scripting 101 Declaring and Initializing Variables 5

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 11: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Unlike Option Explicit which affects the entire script On Error Resume Next applies to only theportion of the script (eg the scriptrsquos body a function a subroutine) that defines it On ErrorResume Nextrsquos narrow scope lets you control precisely when and where itrsquos in effect (VBScriptdoesnrsquot support Visual BasicrsquosmdashVBrsquosmdashOn Error Goto Label construct) When you use the OptionExplicit and On Error Resume Next directives correctly they can make VBScript routines morerobust and user-friendly and play an important role in debugging scripts

VBScript VariablesEarlier I said declaring variables in VBScript is optionalmdashand it is However engaging in the exer-cise of defining your scriptrsquos variables can be well worth your time and effort for several reasonssuch as debugging and script maintenance Declaring your scriptrsquos variables also requires you toconsider the environment and objects with which your script interacts which can result in better-designed scripts that do what you intend them to do

A VBScript variable is simply a named memory location that contains some value The valuemight be a number a string or some other data type that the language supports The variablename is the mechanism through which you assign a value to a variable Declaring VBScript vari-ables identifies the names that yoursquoll use to refer to the data your script manipulates

You use the Dim statement to declare VBScript variables In demovbs the variable declara-tions follow the script directives at the beginning of the script VBScript supports one primary datatype variant You can think of variants as general-purpose variables that arenrsquot bound to a specifictype When you declare a VBScript variable using Dim you donrsquot supply additional type informa-tion as you do in VB Instead VBScript determines a variablersquos type at runtime based on the vari-ablersquos contents and the usage context VBScript supports many different data subtypes andcorresponding data conversion functions that let you morph variants to your heartrsquos content Formore information about VBScript variables download the free VBScript HTML Help file(vbsdocexe) at httpmsdnmicrosoftcomscriptingvbscriptdownloadvbsdocexe

Variable InitializationVariable initialization is nothing more than assigning a known value to a variable before you usethe variable In demovbs I initialize several variables before using the variables in the scriptrsquosbody You can initialize a variable to one value such as a number or a string or to a more com-plex value constructed from multiple elements

For example in the variable initialization section of demovbs the script assigns to strLogFilethe concatenation (from VBScriptrsquos amp operator) of three substrings The first substring (ldquocrdquo) andthird substring (ldquologrdquo) are straightforward The second or middle substring retrieves the value ofWScriptrsquos ScriptName property (in this case ldquodemovbsrdquo) and splits the string into two strings at thedot () In this example I append the subscript (0) to the end of the function call to force the Splitfunction to return only the first element (ldquodemordquo) of the array of elements that Split ordinarilyreturns The end result is a log file name that is identical to the script name without the extension

Constant DefinitionsConstants are named values that donrsquot change throughout the execution of a script VBScript sup-ports two types of constants literal and intrinsic Literal constants are constants that you define forthe purpose of making your script more intelligible Letrsquos say that you write a script that uses the

6 Guide to VBScripting

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 12: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

value of Pi Rather than hard-coding the numeric value each time the script needs it you mightdefine the following literal constant Const Pi = 31415926535897932384626433832795 When youneed to reference the value of Pi in your script you simply use the constantrsquos name (ie Pi) Inthis example referring to the name is much easier than (and significantly reduces potential typingerrors from) coding the numeric value each time the script needs to use Pi Furthermore if youneed to change the value of a constant at some later date you need to update the constantrsquos valuein only one place in the script in the line where you defined the constant You can assign onlyscalar values to VBScript literal constants The language doesnrsquot support constants constructed fromother constants or expressions

Intrinsic constants are constants that are built into the VBScript language to make the languageeasier to use and make your scripts easier to read and maintain Some of my favorite intrinsic con-stants include the escape sequence constants such as vbNewLine and vbTab that represent ANSIcharacter codes which yoursquoll find sprinkled throughout demovbs The VBScript Language Refer-ence and the Scripting Run-Time Reference in the VBScript Help file provide a complete list ofconstants

VBScript doesnrsquot let you use constants that other objects such as the scripting runtimersquosFileSystemObject and ADSI define However Microsoft plans to include this capability in the nextrelease of WSH In the interim if you want to use constants that other objects define simply dupli-cate the constant definition in your script In the constant definitions section of demovbs I definethe local constant OpenFileForReading to mimic the behavior of FileSystemObjectrsquos OpenFileFor-Reading constant

Demovbs EndBefore I go I should tell you what the demo script in Listing 1 does Demovbs simply runsNTrsquos ipconfigexe utility writes the commandsrsquo output to a file opens and displays the filedeletes the file and records the success or failure of each major action along the way to a logfile Then demovbs opens the resulting log file displays the file deletes the file and exits InChapter 2 Irsquoll examine one of the more important elements generally found in the body of ascript object handling

Chapter 1 Scripting 101 Declaring and Initializing Variables 7

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 13: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Chapter 2

Scripting 101 Working with Objects By Bob Wells

In Chapter 1 I explained how to declare and initialize variables in Windows Script Host (WSH)scripts that you create using VBScript In this chapter I discuss the most important job you per-form in the script body working with objects

Objects Regardless of the tasks your scripts perform at some point yoursquoll create and interact with objectsWhether implicitly or explicitly all WSH scripts create objects Understanding what an object iswhat an object provides and how to create and interact with objects is key to successfully usingWSH Although working with objects might be old hat to those of you with a Visual Basic (VB)background quite the opposite is true for individuals with only a batch file background

Objects vs Utilities WSH scripts and batch files have numerous significant differences but none more important thanthe transition away from utilities and toward objects Historically developers used batch files toglue together system resource kit and third-party command-line utilities Provided that you foundutilities to support all the tasks that you wanted to perform this approach worked fine Unfortu-nately developers often hit roadblocks along the way If the utility the batch file called failed toprovide some required option the developer had to scour the Internet for another utility to fill thevoid Sound familiar

Figure 1 shows how Windows NTrsquos graphical applications and utilities call Win32 APIs to runthe task that the application or utility performs Unfortunately Win32 APIs arenrsquot suitable for ad hocscripts and calling Win32 APIs from scripts is almost impossible Therefore NT limited scripting tothe functionality that the utilities provided This limitation led to a perception that Windows wasscripting-challenged (especially compared to UNIX) In fact the limited functionality led to a prolif-eration of third-party and open-source scripting tools to address the lack of Win32 scriptability

So what has changed As Irsquove mentioned part of the solution is WSH WSH interacts withobjects specifically COM automation objects to eliminate the need to find utilities that support allthe tasks you want to perform WSH provides a lightweight scripting environment capable ofcalling the same set of system services that the native NT graphical applications call

The more significant piece of the solution pertains to the API As Figure 2 shows Microsoft isusing COM to expose almost all system services in such a way that scripts and more traditionalsystem programming languages (eg C++) call the same set of interfaces to perform a desiredtask How is this standardization possible With COM system and application developers candevelop their applications so that COM-aware scripting environments such as WSH can interactwith and control COM-enabled services and applications

9

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 14: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Figure 1How NTrsquos graphical applications and utilities call Win32 APIs to

run the task that the application or utility performs

Figure 2COM exposing system services

For example in addition to abstracting multiple and disparate directory services Active Direc-tory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000Active Directory (AD) management tools use Similarly Windows Management Instrumentation

Win32 API

MMC

System andPerformance

Data

ServiceControl

Manager

SAMActive

DirectoryRegistryEvent

Log

MMC ActiveDirectory Snap-In

BatchFilesCgtutilities

COM-Enabled System Services (ADO ADSI CDO WMI)

WSHScripts

OK

User Manager

Win32 API

Server Manager

CgtutilitiesScripts

PerformanceData

SystemData

ServiceControl

ManagerSAMRegistry

EventLog

OK

10 Guide to VBScripting

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 15: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

(WMI) provides COM-savvy scripts with the ability to fetch read and set the same set of Win32system and performance data that Microsoft Systems Management Server (SMS) 20 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access Youleverage these services by utilizing these COM objects in your scripts The first step is to under-stand what an object is

What Is an Object An object is simply a thing Each object has a set of characteristics or attributes that describe theobject and the actions it performs Network OSs messaging systems applications and program-ming languages generally classify objects in terms of a user a group a computer a printer a net-work or an application These entities are all objects in the IT world Each of these objects has aset of properties that uniquely describe it Each object might also perform an action using itsmethods So in the computer world properties describe an object and objects use methods to per-form actions

Letrsquos consider a user object Properties of a user object might include username full name andpassword A user object might use methods to create delete or set passwords You must have auser object before you can interact with it so letrsquos take a look at how to create objects

Creating Objects You might be interested to learn that WSH is a set of objects WSH includes three primary objectsWScript Network and Shell The WScript object provides the script execution environment TheNetwork object provides properties and methods typically associated with network and printerconnections The Shell object provides methods and properties associated with the desktop shellenvironment variables and the registry

Before you can access an objectrsquos methods and properties you must first create an instance ofthe object As part of the script execution environment WScript includes two methodsmdashCreateOb-ject and GetObjectmdashthat you can use to create objects Using these methods is a concept that rep-resents a radical departure from calling utilities inside of batch files

VBScript also provides CreateObject and GetObject as functions which yoursquoll generally wantto use rather than the WScript methods Using WScriptrsquos CreateObject or GetObject methods addsan additional layer of work and is slightly less efficient than using the analogous VBScript func-tions WScript includes these methods to support third-party script engines that might not providea mechanism to create objects

Before we look at some examples you need to be aware of a couple of exceptions to therequirement that you create the object before you use it The first exception concerns WScriptRecall that I said every WSH script creates objects Running a WSH script implicitly creates aWScript object Therefore you can call any WScript method or read any WScript property withoutan explicit call to CreateObject

The VBScript Err object is the second object that WSH scripts automatically create For moreinformation about the VBScript Err object see Chapter 1 Now letrsquos create some objects A goodplace to start is with syntax and definitions

Chapter 2 Scripting 101 Working with Objects 11

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 16: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

CreateObject The CreateObject function creates and returns a reference to an automation object The functionhas one mandatory parameter and one optional parameter In the code line

Set objReference = CreateObject(ldquostrAppstrObjrdquo [ ldquostrServerNamerdquo])

the mandatory two-part parameter is strAppstrObj which identifies the name of the application orcomponent containing the target object and the class name of the object to create This applicationand object pair is also a programmatic identifier (ProgID) The optional parameter strServerNameidentifies the name of the server on which the target object resides When supported strServer-Name lets you create and interact with objects installed on remote machines Microsoft added thisfeature to the CreateObject function in VB 60 and expects to include the feature in the Win2KWSH and VBScript releases

CreateObject returns a reference to the newly created object Typically you assign the refer-ence to an object variable so that you can interact with the object within your script In the pre-vious code line VBScriptrsquos Set statement assigns the object reference that CreateObject returns tothe objReference variable After you obtain a valid object reference you can invoke the objectrsquosmethods and read or set the objectrsquos properties The objectsvbs example script in Listing 1 demon-strates how to use the WScript CreateObject method and VBScriptrsquos CreateObject function

At callout A you can see that WScript methods (WScriptEcho) and properties (egWScriptApplication WScriptFullname) are available immediately without an explicit call to Cre-ateObject At callout B the script uses WScriptrsquos CreateObject method to create a WSH Networkobject In the string ldquoWScriptNetworkrdquo WScript is the application name and Network is the objectname The Set command initializes the objNetwork variable with the object reference that the Cre-ateObject method returns After you have a valid object reference you can interact with the object

For example in callout D the script echoes the values of the Network objectrsquos Computer-Name UserDomain and UserName properties As you can see at callout D you access the objectrsquosproperties using the object reference (objNetwork) followed by a dot () and the name of theproperty that you want to read Many properties are read-only as is the case with the Networkobjectrsquos three properties

Callout C demonstrates how to create a WSH Shell object using VBScriptrsquos CreateObject func-tion Notice the WScript ProgID doesnrsquot preface CreateObject Therefore callout C calls theVBScript CreateObject function rather than WScriptrsquos CreateObject method In this case WScript isthe application name Shell is now the object name and objShell gets initialized to the object refer-ence that CreateObject returns

At callout E the script invokes the Shell objectrsquos Run method Similar to how you work withthe objectrsquos properties you invoke the objectrsquos methods using the object reference followed by adot () and the method name and any parameters that the method supports The scriptrsquos commentscontain details about the different ways to invoke the Run method

So what are some of the common objects yoursquoll likely encounter as you venture deeper intoWSH Table 1 identifies several common application and object names that you might use withCreateObject As yoursquoll see next you can also use GetObject to breathe life into scripts

12 Guide to VBScripting

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 17: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

LISTING 1 Objectsvbs

Option ExplicitDim objNetwork objShell intRC

lsquo Constants that the Shell Objectrsquos Run method usesConst vbHide = 0Const vbNormalFocus = 1Const vbMinimizedFocus = 2Const vbMaximizedFocus = 3Const vbNormalNoFocus = 4Const vbMinimizedNoFocus = 6

lsquo Every WSH script automatically creates a WScript object lsquo You can immediately invoke WScript methods and read lsquo WScript properties as WScriptrsquos Echo method and numerous lsquo properties demonstrate

WScriptEcho ldquoWScript Propertiesrdquo amp vbNewLine amp _ Aldquo________ amp vbNewLine amp _ldquoApplication ldquo amp WScriptApplication amp vbNewLine amp _ldquoFullname ldquo amp WScriptFullname amp vbNewLine amp _ldquoInteractive ldquo amp WScriptInteractive amp vbNewLine amp _ldquoName ldquo amp WScriptName amp vbNewLine amp _ldquoPath ldquo amp WScriptPath amp vbNewLine amp _ldquoScriptFullName ldquo amp WScriptScriptFullName amp vbNewLine amp _ldquoScriptName ldquo amp WScriptScriptName amp vbNewLine amp _ldquoVersion ldquo amp WScriptVersion amp vbNewLine

lsquo To interact with other objects you must first create a reference lsquo to the target object Here I use WScriptrsquos CreateObject methodSet objNetwork = WScriptCreateObject(ldquoWScriptNetworkrdquo) Blsquo ^^^^^^^^^^ ^^^^^^^^^^^^^^lsquo The object reference variable is first followed by strAppstrObj

lsquo Here I use the more efficient VBScript CreateObject functionSet objShell = CreateObject(ldquoWScriptShellrdquo) Clsquo After you have a valid object reference you access the objectrsquoslsquo properties using the objRefPropertyName syntaxWScriptEcho ldquoProperties of the Network Object (read-only)rdquo amp _ DvbNewLine amp ldquo__________________rdquo amp vbNewLine amp _ldquoComputerName ldquo amp objNetworkComputerName amp vbNewLine amp _

ldquoUserDomain ldquo amp objNetworkUserDomain amp vbNewLine amp _ldquoUserName ldquo amp objNetworkUserName

lsquo You invoke the objects methods using thelsquo objRefMethodName([Parameter List]) syntax objShellRun ldquonotepadexerdquo vbMaximizedFocus FALSE EintRC = objShellRun(ldquowordpadexerdquo vbMinimizedFocus FALSE)

lsquo Notice the difference between the two invocations of the Shellrsquos lsquo Run method The first invocation doesnrsquot enclose the parameter list lsquo in parentheses The second invocation encloses the parameter list lsquo The rule is that when using a method as an RValue (appearing onlsquo the right-hand side of an assignment statement) you canlsquo enclose the parameter list in parentheses otherwise you canrsquot

lsquo When yoursquore done with an object you release the reference usinglsquo VBScriptrsquos Nothing keywordSet objNetwork = NothingSet ObjShell = Nothing

Chapter 2 Scripting 101 Working with Objects 13

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 18: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Table 1 Common CreateObject Application and Object Names

GetObject Similar to CreateObject GetObject also returns a reference to an automation object HoweverGetObject supports a slightly different set of parameters

Set objReference = GetObject([ldquostrMonikerrdquo] [rdquostrClassrdquo])

The brackets ([]) mark both parameters as optional You can supply both parameters but you mustpass GetObject at least one of the two parameters

The first parameter strMoniker identifies a persistent object that the target automation serveror component understands such as a Microsoft Excel spreadsheet file In the case of ADSI themoniker is one of the four ADSI namespaces LDAP WinNT NDS or NWCOMPAT WMIrsquosmoniker is WINMGMTS

The second parameter strClass is identical in terms of content and syntax to the two-partstrAppstrObj ProgID that CreateObject uses The code lines in Figure 3 are all valid forms ofGetObject

When do you use CreateObject and when do you use GetObject Experience has taught meto use GetObject primarily with ADSI and WMI I use CreateObject for everything else Howeverexceptions exist Table 2 shows various scenarios in which you might use CreateObject andGetObject

Where do you learn the details about the objectrsquos methods and properties And how do youdetermine a specific objectrsquos application name class or object name Your first stop should be thedocumentation that accompanies the technology Yoursquoll also want to make sure you check out theMicrosoft Developer Network (MSDN) Library at httpmsdnmicrosoftcomlibrary This library isalso available on CD-ROM via subscription

Now is the time to start looking for opportunities to replace those old batch files that calloption-inhibited command-line utilities As you do recognize that learning this new object-basedapproach to scripting might require extra effort on the front end The payoff will come when yourealize the degree to which yoursquore able to automate the back end Todayrsquos Win32 platform is most

ApplicationObject FunctionExcelApplication Returns a reference to a Microsoft Excel automation objectWordApplication Returns a reference to a Microsoft Word automation objectScriptingDictionary Creates a Scripting runtime Dictionary objectScriptingFileSystemObject Creates a Scripting runtime FileSystemObjectWScriptNetwork Creates a WSH Network objectWScriptShell Creates a WSH Shell objectADODBConnection Establishes a connection with a data source using ActiveX Data ObjectsCDONTSNewMail Creates a Collaboration Data Object NewMail object to construct and send

an email message

14 Guide to VBScripting

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 19: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

certainly scriptablemdashand tomorrowrsquos becomes even more so as these services and technologiesconverge in Win2K Create an object and have fun

Figure 3 Valid Forms of GetObject

Table 2 Scenarios for Creating Objects

Method DescriptionCreateObject Creates a new instance of an automation server

Creates additional instances (multiple copies) of an already running serverCreates a reference to an object installed on a remote machine (not yet available in WSH and VBScript)

GetObject Obtains a reference to an automation server that is already running without creatingadditional instancesCreates a new instance of an automation server based on a registered file type or moniker

Rem Examples using WScriptrsquos GetObject method

Set objExcel = WScriptGetObject(ldquocusersxlsrdquo)Set objExcel = WScriptGetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = WScriptGetObject(ldquordquo ldquoWScriptNetworkrdquo)Set objDomain = WScriptGetObject(ldquoWinNTLABDomainrdquo)

Rem Examples using VBScriptrsquos GetObject functionSet objExcel = GetObject(ldquocusersxlsrdquo)Set objExcel = GetObject(ldquocusersxlsrdquo ldquoExcelApplicationrdquo)Set objNetwork = GetObject(ldquordquordquoWScriptNetworkrdquo)Set objWMI = GetObject(ldquowinmgmtsrdquo amp _ldquoimpersonationLevel=impersonaterdquo amp ldquodell610rdquo)

Chapter 2 Scripting 101 Working with Objects 15

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 20: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Chapter 3

VBScript TechniquesBy Mike Otey

VBScript one of the most powerful and underused features in the Windows environment providesthe same powerful programming tools (eg variable support structured program control theability to leverage COM objects) that yoursquoll find in full-featured development languages Some basicbut essential scripting techniques include the following

1 CommentsmdashLiberal use of comments lets you quickly decipher a scriptrsquos purpose monthsafter yoursquove forgotten about the script The apostrophe (lsquo) is the VBScript comment indicator

rsquovbsamplevbs -- Sample Script for Windows amp NET Magazine

2 Option ExplicitmdashYou should add the Option Explicit statement to the beginning of a scriptto force yourself to explicitly declare all variables in the script Variables are named storagelocations that contain values the script can modify By default scripts automatically create avariable on the first reference to it However this capability can mask minor typos in thescript Using Option Explicit can save you hours of debugging

3 DimmdashDim statements let you create variables Variable names must begin with analphabetic character canrsquot contain dots and must contain fewer than 256 characters Manylanguages require you to specify the data type of each variable However VBScriptsupports only the variant data type (which can contain all types of data) so you donrsquotneed to declare a specific data type for VBScript variables

Dim myVariable

4 AssignmentmdashAfter you create a new variable you can use the Assignment operator (=) toassign a value to it The following line assigns the value of 3 to myVariable

myVariable = 3

5 MathmdashVBScript provides support for the full range of mathematical expressions Thefollowing line shows how to perform simple math calculations and divide the result by thecontents of myVariable

myVariable = ((5 + 1) 2)myVariable

6 ConcatenationmdashA common VBScript technique is to combine the contents of differentstrings You can use the Concatenation operator (amp) to create a new string

myVariable = ldquoThe value of myVariable isrdquo amp myVariable

7 ConstantsmdashConstants like variables are named values that you can use in your scriptsAlthough you can alter the contents of variables you canrsquot alter the value of a constant

const myTitle = ldquoVBSamplerdquo

17

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 21: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

8 MsgBoxmdashYou can use the MsgBox function to display messages to the user The followingexample shows how to display the message contained in myVariable The message boxrsquostitle bar displays the value in myTitle

MsgBox myVariablemyTitle

9 InputBoxmdashYou use the InputBox function to prompt the user for simple input values Thefunction automatically assigns the value that the user enters to the variable on the left ofthe equal sign Note that the InputBox function encloses its argument in parentheses

myVariable = InputBox(ldquoInput 1rdquo)

10 IfThenElsemdashThe If statement is an important logical-flow control function Present invirtually all scripts the If statement evaluates a condition then performs an action basedon whether the condition is met

If myVariable = 1 ThenMsgBox ldquoThe value was 1rdquo

ElseMsgBox ldquoThe value was not 1rdquoEnd if

If you want to step up a level and begin writing productive administrative scripts you can usethe following more advanced VBScript techniques

1 On ErrormdashThe On Error statement lets a script trap runtime errors and continue executingYou can test for errors in the script after each statement has executed

On Error Resume Next

2 InStrmdashThis function lets you locate a substring in a string The function returns the startingposition of the substring or a 0 if the function doesnrsquot find the string In

nPos = InStr(ldquo123345rdquo ldquo33rdquo)

nPos has a value of 3 because ldquo33rdquo begins in the third position of ldquo123345rdquo

3 The Do LoopmdashThis basic mechanism for repeatedly executing a set of statements comesin two forms a Do Until Loop and a Do While Loop The most important distinctionbetween the two loops is that the Do Until Loop always executes at least once

Do Until myValue gt 1myValue = myValue + 1

Loop

4 SubroutinesmdashModularizing your code into subroutines lets you organize your scripts andcreate reusable routines You can define subroutines anywhere in a script You usesubroutines when you donrsquot need to return a value to the calling code

Sub mySub(myValue)MsgBox ldquoInside mySubrdquo amp myValue

End Sub

5 FunctionsmdashFunctions are routines that return a value to the calling code The routineassigns the returned value to the function name

18 Guide to VBScripting

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 22: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Function myFunction(myParm)myFunction = myParm + 1

End Function

6 MsgBoxmdashIn addition to displaying a message the MsgBox function can display buttonsand return the value of the selected button The following example displays a messagebox that contains Yes No and Cancel buttons The script assigns the selected buttonrsquosvalue to nButton

nButton = MsgBox(ldquoClick a buttonrdquo vbYesNoCancel)

7 Select CasemdashUse the Select Case statement to compare an expression against several otherexpressions

Select Case nButtonCase vbYes MsgBox ldquoYesrdquoCase vbNo MsgBox ldquoNordquoCase Else MsgBox ldquoCancelrdquo

End Select

8 CreateObjectmdashThis statement lets you create an instance of a COM object inside a scriptYou must use the Set statement in conjunction with the CreateObject statement to createobjects To destroy an object set it to Nothing The following example creates an instanceof Microsoft Word

Set myWord = CreateObject_(ldquoWordApplicationrdquo)

9 Object propertiesmdashTo read and write to one of an objectrsquos properties type the objectrsquosname a dot and the property name The following example sets the Word objectrsquos Visibleproperty to True causing the system to display the Word application

myWordVisible = True

10 Object methodsmdashYou also use the dot notation to access an objectrsquos methods Thefollowing example uses the Add method to create a new Word document and shows howto use the TypeText method to insert text

myWordDocumentsAddmyWordSelectionTypeText ldquoText from vbsamplevbsrdquo

Chapter 3 VBScript Techniques 19

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 23: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Chapter 4

Scripting Command-Line SwitchesBy Don Jones

Most Windows administrators rely heavily on running commands at the command line to accom-plish day-to-day administrative tasks and to automate tedious repetitive tasks The best part aboutsuch commands is their switches (aka parameters) which let you customize the commandsrsquobehavior The Net Use command for example wouldnrsquot be as useful without its persistent switchand the Xcopy command would be useless without its many switches

Many administrators also use VBScript to make their lives easiermdashif yoursquore reading this yoursquoveprobably written a few scripts of your own But administrators often donrsquot maximize the flexibilityof their scripts because most administrators donrsquot write their scripts to take advantage of com-mand-line switches

For example letrsquos assume yoursquove written a script called DisableUservbs which Listing 1shows that lets you easily handle employee resignations (To download executable code for thechapter go to httpwwwwinscriptingsolutionscomFiles072494424944zip) The script disablesa user account and the userrsquos home directory share while leaving the userrsquos user account andhome directory intact for archival and administrative purposes

Listing 1DisableUservbs

Adding Flexibility with Switches The problem with DisableUservbs is that its important valuesmdashthe userrsquos account name the nameof the server that contains the userrsquos home directory and the userrsquos domain namemdashare hard-codedin the script Before running the script you need to open the script in Notepad modify those

Dim oUser oShareSvc sServer sUser sUserDomainsServer = ldquoServer1rdquosUser = ldquoDonJrdquosUserDomain = ldquoMYDOMAINrdquo

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

21

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 24: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

values and save the revised script To eliminate having to open and modify the script each timeyou use it you can use command-line switches When your script supports command-lineswitches you can launch the script and provide the necessary values at the command line Forexample the command

wscript disableuservbs-udonj -sserver1 -dmydomain

launches DisableUservbs and passes three valuesmdashthe account name (donj) the server name(server1) and the domain name (mydomain)mdashto the script

The main Windows Script Host (WSH) object WScript passes the three command-line param-eters to the script WScript includes a collection named Arguments which contains one item foreach parameter passed to the script WSH parses the Arguments collection and uses spaces asswitch separators Thus WSH considers every string of characters that has a space on both ends tobe a separate parameter

Your script can easily access the switches through a For EachNext statement such as

Dim oArgFor Each oArg in WScriptArguments WScriptEcho oArgNext

To see how such a loop works type those four lines into the file Ctestvbs Then open a com-mand-shell window and change to the C directory Type

wscript testvbs 1 2 3

on the command line Press Enter and yoursquoll see a pop-up dialog box that contains all threeswitch values 1 2 and 3

To put this capability to use in a batch file you need to use a Select Case statement to ana-lyze each switch and assign its value to a variable Listing 2 shows sample code that looks for the -s and -u switches and assigns their values to the sServer and sUser variables respectively

Listing 2Sample Switch-Analysis Code

The code starts with a For EachNext loop that examines each command-line argument indi-vidually For each argument the script sets the sSwitch variable to the leftmost three characters ofthe argument string (eg -s) The LCase() function makes the argument lowercase so that the

Dim oArg sUser sServer sSwitch sValueFor Each oArg in WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)

Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

End SelectNext

lsquo Display the results of the switch analysisWScriptEcho ldquoServer ldquo amp sServer amp _vbCrLf amp ldquoUser ldquo amp sUser

22 Guide to VBScripting

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 25: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

script treats -s and -S the same The code sets the sValue variable to the remainder of the argu-ment string (ie the switchrsquos value) by assigning to the variable the value of the string minus thefirst three characters

Finally the sample code uses a Select Case construct to analyze each argument and assigneach switchrsquos value to the correct script variable When the argumentrsquos first three characters are -sthe script assigns the switch value portion of the argument to the sServer variable When the argu-mentrsquos first three characters are -u the script assigns the switch value to the sUser variable TheSelect Case statement lets you type the command-line switches in any order just like most com-mand-line tools do

Handling Omitted SwitchesAn ideal script would accept command-line switches and use pop-up dialog boxes to prompt youfor missing information Such a script would provide the best of both worlds command-line switchesso that you can easily launch the script and provide the necessary parameter values and pop-updialog boxes for any required switches that yoursquove forgotten Incorporating this capability is easyJust add a few DoLoop statements that check for missing values after the For EachNext loopListing 3 shows an example Yoursquoll need to add a DoLoop construct for each required parameter

Listing 3 Checking for Missing Values

Listing 4 shows a new version of DisableUservbs called NewDisableUservbs that incorporatesboth command-line and pop-up dialog capabilities Callout A in Listing 4 shows the added codeNewDisableUservbs includes three command-line switches

bull -s for the name of the server that contains the userrsquos home directorybull -u for the user account namebull -d for the name of the domain in which the userrsquos account is located

This script works in Windows 2000 and Windows NT domains Note that NewDisableUservbs usesMicrosoft Active Directory Service Interfaces (ADSI)

As you can see adding command-line switch capability to your scripts makes them muchmore flexible When a script supports command-line switches you donrsquot have to open and modifythe script each time you use it Instead you can quickly launch a script and provide the necessaryinformation at the command line And when a script incorporates pop-up dialog boxes thatprompt you for missing information you can even launch the script by simply double-clicking thescript and providing parameters in the pop-up dialog boxes

Do While sUserName = ldquordquosUserName = InputBox(ldquoUser name to disablerdquo)

Loop

Chapter 4 Scripting Command-Line Switches 23

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 26: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Listing 4NewDisableUservbs

Dim oUser oShareSvc sServer sUser sUserDomain

Dim oArg sSwitch sValue Alsquo Check command-line switchesFor Each oArg In WScriptArgumentssSwitch = LCase(Left(oArg3))sValue = Right(oArgLen(oArg)-3)Select Case sSwitchCase ldquo-srdquosServer = sValue

Case ldquo-urdquosUser = sValue

Case ldquo-drdquosUserDomain = sValue

End SelectNext

lsquo Prompt for missing valuesDo While sServer = ldquordquosServer = InputBox(ldquoServer name for user sharerdquo)

Loop

Do While sUser = ldquordquosUser = InputBox(ldquoUser namerdquo)

Loop

Do While sUserDomain = ldquordquosUserDomain = InputBox(ldquoUserrsquos domain namerdquo)

Loop

lsquo Get a reference to the Server service and user accountSet oShareSvc = GetObject(ldquoWinNTrdquo amp sServer amp _ldquoLanManServerrdquo)

Set oUser = GetObject(ldquoWinNTrdquo amp sUserDomain _amp ldquordquo amp sUser amp ldquouserrdquo)

lsquo Disable the home directory share (assumeslsquo the share name is the same as the userrsquos name)oShareSvcDelete ldquofilesharerdquo sUser

lsquo Disable the user accountoUserPut ldquoUserFlagsrdquo oUserUserFlags Or 2oUserSetInfoWScriptEcho ldquoCompleterdquo

24 Guide to VBScripting

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 27: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Chapter 5

Adding Users in Bulk By Don Jones

Administrators encounter this scenario all the time You show up on Monday morning and thehuman resources (HR) department has a dozen new user accounts for you to set up This setupdoesnrsquot include just accounts either but the new usersrsquo home directories dial-in permissions andmore Instead of spending the morning checking on your Microsoft Exchange Server or catchingup on the latest news on the Web yoursquore stuck entering new-user information from a spreadsheet

Scripting to the rescue This type of task is not only well suited to scripting-based automationitrsquos also a great way to demonstrate several different scripting capabilities Let me show you ascript that can automate the task of adding new users to your Windows NT 40 domain

Getting Started For this example letrsquos assume yoursquore working with an NT domain called Corporate that has a PDCcalled NT4PDC You must set up a basic infrastructure to let your script work First create aMicrosoft Excel spreadsheet such as the one that Figure 1 shows The spreadsheet should includeinformation for each user that yoursquore adding to the domain In this example Irsquove included columnsfor the userrsquos ID full name description and home directory Universal Naming Convention (UNC)path a column for a comma-separated list of user groups to which the user should belong and acolumn for indicating whether the user needs to have dial-in permissions You can distribute yourspreadsheet to HR department personnel and ask them to use it when they submit new-userrequests (Notice that the list of user groups doesnrsquot include the Domain Users group because bydefault all users belong to Domain Users)

Next create a System ODBC Data Source Name (DSN) that points to the spreadsheet asFigure 2 shows (I recommend that you create a System DSN rather than a User DSN Otherwise ifanother user logs on to the same machine to run the script the script will fail) The DSN pointsonly to the spreadsheetrsquos location so you can save new spreadsheets to the same location and theDSN will find them In this example Irsquove created a DSN called Excel that uses the Excel ODBCdriver to point to my spreadsheet If your computer doesnrsquot have an Excel driver you must installthe latest version of Microsoft Data Access Components (MDAC) which you can download fromhttpwwwmicrosoftcomdata

Finally make sure that Windows Script Host (WSH) and Active Directory Service Interfaces(ADSI) are available on the computer on which yoursquoll run the script (Both are present on Win-dows 2000 Professional Win2K Server Win2K Advanced Server and Win2K Datacenter Servercomputers) Note that you must install ADSI even if yoursquore going to be working with an NTdomain If you want to set up these components on an NT workstation you must install WSHfrom the Microsoft Windows NT 40 Option Pack and ADSI from the Microsoft Platform softwaredevelopment kit (SDK) which is available from httpwwwmicrosoftcommsdownloadplatformsdksdkupdate

25

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 28: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Figure 1Excel spreadsheet for adding users to a domain

Figure 2Creating a System ODBC DSN that points to a spreadsheet

26 Guide to VBScripting

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 29: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Writing the Script When all the preliminary pieces are in place you can get the script ready Listing 1 shows thecomplete bulk-usersvbs script (To download executable code for this chapter go tohttpwwwwinscriptingsolutionscomFiles2253722537zip) Because a lot is going on in thisscript Irsquoll describe each section

Listing 1Bulk-usersvbs

rsquo Part 1 Use ADO to open the Excel spreadsheetDim oCNSet oCN = CreateObject(ldquoADODBConnectionrdquo)oCNOpen ldquoExcelrdquo

Dim oRSSet oRS = oCNExecute(ldquoSELECT FROM [Sheet1$]rdquo)

lsquo Part 2 Use ADSI to obtain a reference to the NT domainDim oDomainDim sPDCsPDC = ldquoNT4PDCrdquoSet oDomain = GetObject(ldquoWinNTrdquo amp sPDC)

lsquo Part 3 Open an output text file to store usersrsquo initial passwordsDim oFSO oTSSet oFSO = CreateObject(ldquoScriptingFileSystemObjectrdquo)Set oTS = oFSOCreateTextFile(ldquoCpasswordstxtrdquoTrue)

lsquo Part 4 For each record in the record set add the user set the lsquo correct user properties and add the user to the appropriate groups

lsquo Create the necessary variablesDim sUserID sFullName sDescriptionDim sHomeDir sGroups sDialInDim sPassword oUserAcct oFolderDim sGroupList iTemp oGroup

lsquo Define the base path in which to create the home directoriesDim sHomePath sMsgsHomePath = ldquoiridis1c$usersrdquo

lsquo Go through the record set one row at a timeDo Until oRSEOF

lsquo Get the user information from this rowsUserID = oRS(ldquoUserIDrdquo)sFullName = oRS(ldquoFullNamerdquo)sDescription = oRS(ldquoDescriptionrdquo)sHomeDir = oRS(ldquoHomeDirectoryrdquo)sGroups = oRS(ldquoGroupsrdquo)sDialIn = oRS(ldquoDialInrdquo)

lsquo Make up a new passwordsPassword = Left(sUserID2) _amp DatePart(ldquonrdquoTime) amp DatePart(ldquoyrdquoDate) _amp DatePart(ldquosrdquoTime)

lsquo Create the user accountOn Error Resume NextSet oUserAcct = oDomainCreate(ldquouserrdquosUserID)If Err ltgt 0 ThensMsg = ldquoAn error occurred creating user ldquo _amp sUserID amp vbCrLf amp vbCrLf

sMsg = sMsg amp ldquoThe error is ldquo _amp ErrDescription

MsgBox sMsgEnd IfOn Error Goto 0

Continued

Chapter 5 Adding Users in Bulk 27

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 30: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Listing 1 continuedlsquo Set account propertiesoUserAcctSetPassword sPasswordoUserAcctFullName = sFullNameoUserAcctDescription = sDescriptionoUserAcctHomeDirectory = sHomeDir

lsquo Set RAS permissionIf sDialIn = ldquoYrdquo ThenoUserAcctRasPermissions = 9

ElseoUserAcctRasPermissions = 1

End If

lsquo Save the accountoUserAcctSetInfo

lsquo Get a reference to the new account This step provides a valid SID lsquo and other informationSet oUserAcct = GetObject(ldquoWinNTrdquo _amp sPDC amp ldquordquo amp sUserID amp ldquouserrdquo)

lsquo Write the password to a fileoTSWrite sUserID amp ldquordquo amp sPassword _amp vbCrLf

lsquo Part 4A Add the user account to groups Use the Split function to lsquo turn the comma-separated list into an arraysGroupList = Split(sGroups ldquordquo)

lsquo Go through the array and add the user to each groupFor iTemp = 0 To uBound(sGroupList)

lsquo Get the groupSet oGroup = GetObject(ldquoWinNTrdquo amp _sPDC amp ldquordquo amp sGroupList(iTemp) _amp ldquogrouprdquo)

lsquo Add the user accountoGroupAdd oUserAcctADsPath

lsquo Release the groupSet oGroup = Nothing

Next

lsquo Part 4B Create the userrsquos home directory (Append the UserID to lsquo the Home Path variable)Set oFolder = oFSOCreateFolder(sHomePath _amp sUserID)

lsquo Part 5 Release the user accountSet oUserAcct = Nothing

lsquo Move to the next row in the record setoRSMoveNext

Loop

lsquo Part 6 Final clean up and close downoRSCloseoTSCloseWScriptEcho ldquoPasswords have been written ldquo _amp ldquoto Cpasswordstxtrdquo

28 Guide to VBScripting

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 31: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Part 1 of bulk-usersvbs uses ActiveX Data Objects (ADO) to create a connection to the ODBCDSN called Excel Because that DSN points to my Excel spreadsheet I have a database connectionto the spreadsheet Next I use the Connection objectrsquos Execute method to retrieve all the informa-tion on Sheet1 of the spreadsheet This information resides in an ADO Recordset object

Part 2 of bulk-usersvbs uses ADSI to obtain a reference to the PDC To use this script youmust replace NT4PDC with the name of the PDC in your environment Changing the PDC name iseasy because Irsquove defined it in a variable rather than in each statement that requires the PDCname Because the PDCrsquos SAM is the source for the domainrsquos account list this reference lets mework with the domain accounts

Part 3 of the script uses the Scripting Runtime Libraryrsquos FileSystemObject object to open a newtext file called passwordstxt I use this txt file to store the passwords I create for the new useraccounts The CreateTextFile method returns a reference to a TextStream object which I store inthe oTS variable This step essentially makes the oTS variable represent the open text file which inturn makes writing information to the file later easy

The Work Begins Now all the preliminary scripting work has been done and Part 4 of bulk-usersvbs can begin tocreate user accounts The first few lines of Part 4 simply declare the variables that the script usesThe script then sets up the base path to the server on which the userrsquos home directory will be cre-ated Note that this path connects to the C$ administrative share

The main work of this script is accomplished within the DoLoop statement which handlesthe record set one line at a time The first six lines of code within the loop retrieve the new userrsquosinformation from the record set and store that information in variables (This step isnrsquot strictly nec-essary but it makes the information easier to work with) Notice that the field names in theRecordset object correspond to the column names in the Excel spreadsheet Next I create apseudo-random password by combining the first two characters of the new userrsquos ID the minutesfrom the system clock the Julian date (ie a number from 1 to 365 indicating the day of the year)and the seconds from the clock You can also create a password based on the username SocialSecurity number or other information

The next few lines actually create the user account in the domain The Create method requirestwo parameters the type of object yoursquore creating (eg a User object) and the identifier (eg theuserrsquos ID) The method returns a reference to the newly created User object which I assign to theoUserAcct variable Capturing this reference in a variable lets the script immediately set the proper-ties of the account including the password full name description home directory and RAS per-missions Note that the script includes error checking to specify whether a problem occurred whenthe script tried to create the user account For example if the Excel spreadsheet contains a user-name that already exists the script will encounter an error when it tries to create the duplicateusername The script will then display a message telling you about the error

After setting the account properties the script sets RAS permissions Note that the value 9 per-mits dialing in while the value 1 denies it You can look up these values in the ADSI documenta-tion which is available at httpmsdnmicrosoftcomlibrarydefaultasp (Navigate to Networkingand Directory Services Active Directory ADSI and Directory Services SDK Documentation Direc-tory Services Active Directory Service Interfaces) Next the SetInfo method saves all the accountproperties to the domain then the script obtains a fresh reference to the user account When the

Chapter 5 Adding Users in Bulk 29

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 32: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

account is saved the domain generates a SID and sets other internal information (eg theaccountrsquos creation date initial security attributes) Obtaining a new reference to the account givesthe script access to that internal information which is required for the next major stepmdashadding theuser to the proper groups Part 4A of the script accomplishes this step Before moving on to Part4A I use the Write method of the TextStream object to save the userrsquos ID and password to the textfile Writing passwords to a file is a potential security breach of course which is why you mightprefer to create nonrandom passwords that you donrsquot need to write to a file If yoursquore certain thatthe password file wonrsquot be compromised though this method is a convenient way to create pass-words for new users

Because the Excel spreadsheet can contain a comma-separated list of groups to which the usershould belong I used the VBScriptrsquos Split function to turn that list into a string array The Splitfunction looks for commas in the sGroups string and creates an array called sGroupList in whicheach element in the array is one group name I then use a ForNext statement to go through eachelement in the array The uBound function tells the script how many elements are in the sGrou-pList array so that the script executes the loop the proper number of times Within the ForNextloop I use ADSI again to obtain a reference to the group to which I want to add the user I usethe oGroup variable to store the reference then I use the Add method to add the user TheADsPath property is an internal piece of information that the domain provides when the account issaved After adding the user I release the reference to the group by setting the variable to theNothing keyword This step isnrsquot strictly necessary but itrsquos good scripting practice and helpsimprove performance

When the user is in all the correct groups I use the FileSystemObject object again to createthe userrsquos home directory This process takes place in Part 4B of bulk-usersvbs This step creates anew folder by using the sHomePath variable and appending the userrsquos ID for the final foldername (Make sure that the Cusers folder already exists otherwise this operation will fail)

Part 5 of the script releases the reference to the User object in preparation for the next user inthe record set The last line in the DoLoop construct moves the record-set pointer to the nextrow so that the loop can work on the next user If the record-set pointer moves beyond the lastuser the End of File (EOF) property is set to True and the loop terminates

Part 6 of the script runs after the DoLoop construct has processed the last user This partsimply closes the Excel spreadsheet closes the text file that contains the new passwords and dis-plays a dialog box that states the script has completed successfully Figure 3 shows User Managerfor Domains with the new user accounts in place

30 Guide to VBScripting

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 33: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Figure 3New user accounts

Do It with a Script Scripting is a great administrative tool because it lets you glue together various pieces of OS func-tionality to achieve terrific results I used ADO the Scripting Runtime Library and ADSImdashthree rel-atively unrelated sets of technologymdashto perform a common time-consuming administrative taskThe examples in this chapter give you a good idea about how you can use a script to make com-plex tasks much easier and how to start exploring ADO and ADSI to come up with custom time-saving solutions

Chapter 5 Adding Users in Bulk 31

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 34: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Chapter 6

VBScript to Generate a List of User Last Logon Times for a Domain By John Savill

Irsquove written a small VBScript file which Listing 1 contains that you can use with the Windowsscripting engine to generate a list of all user last logons (if the last logon time isnrsquot available theuser will be omitted) The file requires that you have Windows Script Host (WSH) installed Anadvantage of using VBScript for this task is that you can change the code to output exactly whatyou want

Listing 1Userloginvbs

To use my VBScript file save the text in Listing 1 as userloginvbs Go to a command promptand enter

cscript userloginvbs

Figure 1 shows a sample outputMy script checks only the PDC If you have BDCs the output values might be incorrect

because last logon times donrsquot update from BDCs to the PDC You might want to modify the scriptto also query your BDCs and disply the latest logon time

rsquo List last logon timeslsquo 2001-03-27 John Savill Jakob Hussfelt httpwwwntfaqcomOn Error Resume NextsEnterDCs = ldquoSAVILLTECHSAVILLNT02rdquosObjects = Split(sEnterDCs ldquordquo)Set oDomain = GetObject(ldquoWinNTrdquo amp sObjects(0))oDomainFilter = Array(ldquoUserrdquo)WScriptEcho ldquoShowing last login times of accounts from ldquo amp oDomainName amp vbNewLineFor Each oDomainItem In oDomainsUsrLogin = oDomainItemLastLoginIf UBound(sObjects) gt= 1 ThenFor ii = 1 To UBound(sObjects)Set oUsr = GetObject(ldquoWinNTrdquo amp sObjects(ii) amp ldquordquo amp oDomainItemName amp ldquouserrdquo)If oUsrLastLogin gt sUsrLogin Then sUsrLogin = oUsrLastLoginNextEnd IfWScriptEcho ldquoUsername ldquo amp Left(oDomainItemName amp Space(22)22) amp ldquoLast login ldquo amp FormatDateTime(sUsrLogin)Next

33

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 35: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Figure 1Sample userloginvbs output

Cgtcscript dtempdisuservbsMicrosoft (R) Windows Scripting Host Version 50 for WindowsCopyright (C) Microsoft Corporation 1996-1997 All rights reserved

Domain SAVILLTECHFull Name=Maria Aala (DIS 120 inactive)Last login=27051999 144424Full Name=Paul J AaronLast login=16081999 130156Full Name=Hany A AbbasLast login=23081999 132546Full Name=Tony S AbbittLast login=27081999 150720Full Name=Adnan AbdallahLast login=16071999 103458Full Name=Tony AbelaLast login=21071999 104320Full Name=Juan Claudio AbelloLast login=25061999 111532Full Name=Marie J B AbreyLast login=07091999 080034Full Name=Philippa AbsilLast login=07091999 063318Full Name=Ace Test account for NetID - Alistair PurvisLast login=28011999 075430Full Name=Chris AckermannLast login=07091999 082120Full Name=Curtis S AdamsLast login=10081999 123202Full Name=Helen R Adams DIS user left 27899Last login=02081999 085258Full Name=Michael Adams Dis 4699 NMFLast login=03061999 085010Full Name=Philip R AdamsLast login=14061999 124900

34 Guide to VBScripting

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 36: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Chapter 7

VBScript to Datastamp Log FilesBy Larry Lai

For administrators who manage applications that generate accumulative log files I have a way torename a file by date For example Oracle creates an Alert log file that can grow quite large Iwrote a VBScript routine which Listing 1 shows that timestamps the log file and renames it with afilename that reflects the date that Oracle created the log The following wrapper batch file callsthe script in Listing 1 so that you can use the AT command to schedule the script to run

cscript datefilevbs nologo

Listing 1DateFilevbs

rsquoDateFilevbslsquoVBScript that renames a log file with the current dateDim StrSource StrNew fso sf systimeStrSource=rdquoSource file fullpathrdquoSet fso = CreateObject(ldquoScriptingFileSystemObjectrdquo)set sf=fsoGetFile(StrSource)systime=now()lsquoYou can skip either of the procedures belowCall Comment(sf) lsquoAdd a timestamp at the end of the source fileCall RenameFile(sf) lsquoRename the source file with the date format of yyyymmddlog

Sub Comment(f)Dim tsConst ForAppending = 8set ts=fOpenAsTextStream(ForAppending)tswriteline cstr(systime)tscloseEnd Sub

Sub RenameFile(f)StrNew=fParentFolder amprdquordquo amp cstr(year(systime)) amp cstr(month(systime)) amp cstr(day(systime)) amp ldquologrdquo

fmove StrNewEnd Sub

35

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 37: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Chapter 8

Simplify Win2K Desktop DeploymentBy Don Baker

How do you quickly deploy 50 Windows 2000 Professional desktops loaded with all the necessaryapplication software While working as a consultant to a large communications company I facedthis challenge and decided to automate the process Irsquod done a lot of reading about WindowsScript Host (WSH) and the time seemed right to see whether I could make it work for me

With disk-imaging software Microsoftrsquos Sysprep utility and some basic knowledge of WSHscripting I was able to take the drudgery out of desktop setup and configuration The process Icame up with has four main steps Create a standard hard disk image write a script to performsome required setup tasks prepare the disk image for cloning and clone the image onto the targetworkstations You too can deploy workstations quickly and easily using the procedure and codedescribed here (of course yoursquoll need to customize the code for your situation)

The Deployment Environment In my situation the company network is a mixture of Novell NetWare 4x servers running inbindery emulation mode and Novell Directory Services (NDS) providing file-and-print services TheWindows NT 40 domain provides access to the application servers The standard desktop OS isWindows 95 but inhouse application developers and administrators were using NT Microsoft Sys-tems Management Server (SMS) 20 and SMS 12 provide hardware and software inventory informa-tion automated software distribution and Help desk remote control

Then our Web application developers decided they needed Win2K Pro so we needed a planfor deploying the OS We decided to use our standard method for building a workstation cloninga disk image onto each workstation

Create a Hard Disk Image To clone a workstation you configure a computer with the desired OS and application softwarethen create an image of the disk that you can copy to another computerrsquos hard disk Disk cloningis a fast and efficient way to set up workstations letting you build and configure a workstationwith all its application software in less than 30 minutes

Several companies make disk-cloning software Irsquove most often used Symantec Ghost andPowerQuestrsquos Drive Image Pro but all the products work similarly You boot the computer to aDOS prompt then start the disk-imaging software You can create an image of an entire disk or asingle partition and save it to another partition drive or network share You can later restore thesaved image to another disk One feature to look for in disk-cloning software is media spanningwhich lets you break up a disk image into smaller pieces This feature is important if your image islarger than 640MB and you plan to store the image on a CD-ROM

Disk cloning works best in environments with a standard hardware platform The video cardnetwork adapter sound cards and so on should be the same in all the computers and should

37

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 38: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

occupy the same slots The hard disks donrsquot all need to be the same size but the disk imageyoursquore loading onto a disk must be no larger than the disk You might need to maintain severaldifferent disk images to keep up with your changing hardware but the fewer images you have tomaintain the better

To prepare for disk imaging load Win2K Pro on a representative workstation Leave the localAdministrator password blank and donrsquot join the domain at this time Install all the application soft-ware that a standard workstation should have and configure the OS and each application

Spend some time thinking about the OS and application settings that you would usually applyRemember that the goal is to perform as little manual configuration as possible on each worksta-tion For example if your word processing application has shared template directories configurethe directory location My company was using an NT 40 domain as the back end so I couldnrsquottake advantage of Win2K Group Policy However I was able to configure a local policy to run alogoff script to update antivirus definitions

Clean up the disk before you create the master image Empty the Recycle Bin Remove all thetemporary files you and the setup process created Clear the Start menursquos Documents list andbrowser history Remove all persistent drive mappings you created while loading applications RunChkdsk to ensure the disk has no file-system errors and clear the Application Security andSystem event logs

Create a 35rdquo network boot disk Copy your disk-imaging software to another 35rdquo disk Restartthe computer by using the network boot disk then map a drive to a network share that has enoughspace to store the disk image When the computer has finished booting insert the second 35rdquo diskand start the disk-imaging software save the hard disk image to the network drive you just mapped

After yoursquove created the disk image you can use a network boot disk to clone workstationsdirectly from the image on the network share Alternatively you can burn the image on a CD-ROM and use the CD-ROM to clone workstations If you follow the CD-ROM approach yoursquollneed a boot disk with CD-ROM drivers or yoursquoll need to make the CD-ROM with the image on itbootable Storing the image on a bootable CD-ROM makes workstation cloning fast and easy Youcan find information about creating bootable CD-ROMs in the documentation that came with yourCD-ROM burner or on the manufacturerrsquos Web site

Write a FinalSetupvbs Script If you like batch files yoursquoll love WSH scripting WSH is a script interpreter (engine) built intoWin2K and Win98 You can install it on NT 40 and Win95 as well The WSH interpreter supportsWSH commands VBScript and JScript (Microsoftrsquos version of JavaScript)

You can use WSH scripting to manipulate the file system automate desktop applicationsmanage a Microsoft SQL Server system and much more Learning WSH scripting is easymdashall youneed is a text editor and a computer with WSH installed The Microsoft Windows Script Web site(httpmsdnmicrosoftcomlibrarydefaultaspurl=nhpDefaultaspcontentid=28001169) has a greatdeal of information available for download

I used WSH and VBScript to write the FinalSetupvbs script in Listing 1 Yoursquoll notice that I likea lot of white space and plenty of comments in a script Comments make a script easier to readand can help you determine what the script does when you open it up months down the road Inmany cases I even retain but comment out any debugging code I added when I wrote andtested the script

38 Guide to VBScripting

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 39: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Listing 1FinalSetupvbs

rsquolsquo TITLE FinalSetupVBS Ver 20lsquo USE Use this to add domain global groups to local groups after the lsquo computer has joined the domain (WIN 2000 Image)lsquo

OPTION EXPLICIT lsquoEnsures variables are declared

ON ERROR RESUME NEXT lsquoKeeps script moving past errors

lsquolsquoDeclare variableslsquoDim oGroup lsquoADSI object created by GetObjectDim oWshShell lsquoShell object to run executable (smsmanexe)Dim sInDomain lsquoUsed to test domain membershipDim sCompName lsquoLocal computer nameDim oWshNet lsquoWshNetwork objectDim sUser lsquoUsername for error checkingDim sMember lsquoCheck for group membership 0 or 1

lsquolsquo Declare constantslsquoConst GLOBAL_GROUP = ldquoWEBDEVrdquo lsquoGlobal group being added to local groupConst LOCAL_GROUP = ldquoAdministratorsrdquo lsquoName of local groupConst DOMAIN = ldquoGONDORrdquo lsquoDomain name

lsquolsquo Create objectslsquolsquoCreate network objectSet oWshNet = WscriptCreateObject(ldquoWscriptNetworkrdquo)lsquoCreate shell objectSet oWshShell = WscriptCreateObject(ldquoWscriptShellrdquo)

lsquolsquo Get local informationlsquosUser = oWshNetUsername lsquoGet logon name of current userSCompName = oWshNetComputername lsquoGet computer name

lsquolsquoConfirm Administrator is logged on quit if notlsquoIF UCASE(sUser) ltgt ldquoADMINISTRATORrdquo THENWscriptEcho ldquoYou must be logged in as ldquordquoADMINISTRATORrdquordquo to run this ldquo amp _

ldquoscript ldquo amp vbCRLF amp vbCRLF amp ldquoLog off and login as ldquo amp _ldquordquordquoADMINISTRATORrdquordquo to the local machine ldquo amp ldquo(ldquo amp sCompName amp ldquo)rdquo amp _vbCRLF amp vbCRLF amp ldquoAfter logging in as ADMINISTRATOR run the ldquo amp _ldquoCWINNTSYSTEM32FinalSetupvbs script againrdquo amp _ldquo to finish the installationrdquo

WscriptQuitEND IF

lsquolsquoMake sure the machine has been added to the domainlsquoif not quit and display messagelsquolsquoGet key value from registrysInDomain = oWshShellRegRead(ldquoHKLMSOFTWARErdquo amp _

ldquoMicrosoftWindows NTCurrentVersionWinlogonDomainCacheGONDORrdquo)

IF sInDomain = ldquordquo THENWscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IFContinued

Chapter 8 Simplify Win2K Desktop Deployment 39

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 40: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

FinalSetupvbs performs the final steps of the setup process before the installer turns a com-puter over to the end user The code confirms that the person running the script is logged on asAdministrator and that the computer has joined the domain The script then adds the WEBDEVglobal group to the Local Administrators group on the computer to enable the Web developers toinstall software and configure their computers

The scriptrsquos first two statements are very important and should be in every script you writeThe OPTION EXPLICIT statement requires you to declare variables before you can use them thushelping you prevent errors in your scripts Declaring variables is optional in VBScript However ifyou donrsquot use OPTION EXPLICIT a typo in a variable name will create a new variable Such anerror might be easy to find in a simple script but not in one that contains hundreds of lines TheON ERROR RESUME NEXT statement prevents your script from stopping if it encounters an errorThe purpose of this statement isnrsquot to ignore errors but to let you deal with them gracefully so thatthey arenrsquot fatal to the script

FinalSetupvbsrsquos next section declares variables You can place all the variables on the sameline separating them with commas or you can place them on separate lines as Irsquove done

Listing 1 continuedIF ERRNUMBER = -2147024894 THEN

WscriptEcho ldquoThe Computer does not belong to ldquo amp DOMAIN amp ldquo domainrdquoWscriptquit

END IF

lsquolsquo Modify group membershipslsquoSet oGroup = GetObject(ldquoWinNTrdquo amp sCompName amp ldquordquo amp LOCAL_GROUP amp ldquogrouprdquo)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP) lsquoIf a lsquomember will return 1 If not 0

IF sMember = 0 THENoGroupadd(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)sMember = oGroupIsMember(ldquoWinNTrdquo amp DOMAIN amp ldquordquo amp GLOBAL_GROUP)lsquoIf a member will return 1 If not 0

IF sMember = -1 THENoWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group has been ldquo amp _

ldquosuccessfully added to the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo amp _5 ldquoLocal Group Modifiedrdquo 064

End IFELSE

oWshShellPopup ldquoThe ldquo amp GLOBAL_GROUP amp ldquo global group is alreadyrdquo amp _ldquo a member of the ldquo amp LOCAL_GROUP amp ldquo local grouprdquo 5 amp _ldquoGlobal Group Existsrdquo 064

End IF

lsquolsquoRun smsmanexe to install SMS 20lsquooWshShellPopup ldquoSMS 20 will now be installed Please wait whilerdquo amp _

ldquo program is loadingrdquo amp vbCRLF amp vbCRLF amp ldquoThe SMS Clientrdquo amp _ldquo Installation will take approximately 5 minutes to completerdquo amp _ 10 ldquoSMS 20 Installationrdquo 064

oWshNetMapNetworkDrive ldquoNrdquo ldquoSMSCPS1SMSLOGONrdquo ldquoguestrdquo ldquordquooWshShellRun ldquoNx86bin00000409SMSMANEXErdquo TRUEoWshNetRemoveNetworkDrive ldquoNrdquo

lsquolsquoDisplay end-of-script message and exitlsquo

MsgBox ldquoThis portion of the setup has been completed ldquo amp _ldquoLogoff and login as the user and setup the printersrdquo

40 Guide to VBScripting

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 41: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

A variable name must begin with a letter and can have as many as 255 characters The name cancontain letters numbers and underscore (_) characters Using a lowercase one-letter prefix to indi-cate the type of data (eg object string integer) stored in the variable is customary

The next section of the script declares constants which are similar to variables except that youcanrsquot change their values after you declare them The script uses three constantsGLOBAL_GROUP LOCAL_GROUP and DOMAIN

To perform real work a script needs to use objects which have methods (functions that anobject performs) and properties (characteristics) Before a script can use an object it must instan-tiate (create) the object Instantiating an object loads it into memory and registers it In WSHscripting you use the WscriptCreateObject() function to instantiate an object FinalSetupvbs usesseveral objects that are built in to WSH

The next section of FinalSetupvbs creates two objects the Network object (WscriptNetwork)and the Shell object (WscriptShell) The Network object lets the script connect to networkresources The Shell object lets the script run an executable manipulate the registry read environ-mental variables create shortcuts and perform several other functions In each case the scriptstores the created object in a variable (oWshNet and oWshShell respectively) and uses the variableto access the objectrsquos methods and properties

The local Administrator must be logged on to the computer for the script to be able to com-plete its tasks To confirm that the user is the local Administrator the script gets the value of theUsername property of the Network object created earlier and stores the value in the sUser variableThe script retrieves the computer name from the Computername property and stores it in thesCompName variable Then the script uses the UCASE() function to convert the value of sUser touppercase and compares the converted value with ADMINISTRATOR If sUserrsquos value isnrsquot equal toADMINISTRATOR the script displays an error message and exits

When the user is the Administrator the script continues to the next step which ensures thatthe computer has joined the domain First the oWshShellRegRead method reads theHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsNTCurrentVersionWinlogonDomain-CacheGONDOR registry subkey and stores the value in the sInDomain variable Then the scriptperforms two checks First it checks whether sInDomain is null (ie whether the registry subkeyis empty) If it is the script displays an error message and exits Second the script checks for thefatal errormdash2147024894 which occurs if the registry subkey doesnrsquot exist and exits gracefully if theerror has occurred If the registry subkey werenrsquot present and the script didnrsquot include the ONERROR RESUME NEXT statement that I mentioned earlier the user would see the error messagethat Figure 1 shows

Next the script adds the NT 40 domain global group to the Administrators local group on thecomputer For this task the script first uses Active Directory Service Interfaces (ADSI) to connect tothe SAM database on the local computer The script creates the oGroup object by using ADSIrsquosGetObject() function to bind to ADSIrsquos WinNT provider After establishing the connection with theWinNT provider the script uses the oGroup objectrsquos IsMember method to verify that the domainglobal group (GLOBAL_GROUP) is a member of the Administrator local group If the global groupisnrsquot a member of the local group the value of the sMember variable is FALSE (0) and the scriptuses the oGroupAdd method to add the global group to the local group The script rechecks thevalue of sMember to ensure that itrsquos TRUE (-1) then uses the oWshShellPopup method to displaya status message and continues running after a 5-second pause

Chapter 8 Simplify Win2K Desktop Deployment 41

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 42: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Figure 1Error message

We use SMS so the last thing the script does is install the SMS client software on the com-puter After displaying an informational message the script uses the oWshNetMapNetworkDrivemethod to map the computerrsquos N drive to the SMS server and the oWshShellRun method to startsmsmanexe When smsmanexe has finished the script disconnects the network drive and displaysa final message

Prepare the Disk Image After yoursquove created the master disk image you use the Sysprep utility to prepare the image forduplication The Sysprep utility comprises three files sysprepexe setupclexe and sysprepinfSysprepexe prepares the disk for cloning and runs setupclexe which generates a unique SID on thecloned image You can use the optional sysprepinf file to automate Syspreprsquos Mini-Setup Wizardprocess During the first boot after cloning the Mini-Setup Wizard will prompt you for any infor-mation sysprepinf doesnrsquot provide such as computer name time zone and domain membership

Sysprep also lets you copy a disk image to a computer that has a compatible hardwareabstraction layer (HAL) but different hardware from the system that provided the image The imagemust contain any drivers not in the Cwinntdriver cachei386drivercab file and sysprepinfrsquos[UNATTENDED] section must specify the location of the additional drivers

You can find a version of Sysprep on the Win2K Pro CD-ROM under supporttoolsdeploycab but a newer version is available at the Microsoft Web site at httpwwwmicrosoftcomwin-dows2000techinfoplanningincrementalsysprep11asp Download the white paper ldquoAutomatingWindows 2000 Deployments with Syspreprdquo and read it before getting started Appendix B of thiswhite paper contains the commands you need to create sysprepinf and ldquoMicrosoft Windows 2000Guide to Unattended Setuprdquo (unattendeddoc) in the deploycab folder on the Win2K Pro CD-ROM provides information about the syntax of the commands

Listing 2 shows the sysprepinf file I created Letrsquos look at each section and the actions that ittells the Mini-Setup Wizard to perform

42 Guide to VBScripting

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 43: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

Listing 2Sysprepinf

UnattendedIn the [Unattended] section the OemPreInstall = no line indicates that yoursquoll use a cloned diskrather than an unattended setup OemSkipEula = yes suppresses the display of the End UserLicense Agreement (EULA) KeepPageFile = 0 causes Win2K to regenerate the computerrsquos pagefileto accommodate any difference in RAM between the master computer and the target computerExtendOemPartition = 1 extends the system partition to fill the remaining space on the diskAnother option is to expand the partition by an amount you specify in megabytes (eg Exten-dOemPartition = 75) leaving the unused disk space available for additional partitions The ExtendOemPartition feature works only on NTFS partitions

A parameter that I didnrsquot use but thatrsquos worth mentioning is OemPnPDriversPath which letsyou add drivers not in the Cwinntdriver cachei386drivercab file When the Mini-Setup Wizarddetects new hardware on the target computer during installation the wizard searches for theappropriate drivers in the drivercab file then if necessary in the location that the OemPn-PDriversPath parameter specifies

GuiUnattendedIn the [GuiUnattended] section OemSkipWelcome = 1 suppresses the display of the Welcomescreen AdminPassword = elyod[ sets the local Administrator password on the computer to the com-panywide standard password (elyod[) used for all NT systems TimeZone = 035 sets the correct timezone for the computer (035 represents Eastern time) The unattendeddoc file contains a table of thetime zone codes OemSkipRegional = 1 ensures that yoursquore prompted for any regional information

[Unattended]OemPreInstall = noOemSkipEula = yesKeepPageFile = 0ExtendOemPartition = 1

[GuiUnattended]OemSkipWelcome = 1AdminPassword = elyod[TimeZone = 035OemSkipRegional = 1

[GuiRunOnce]command01 = cwinntsystem32finalsetupvbs

[UserData]OrgName = ldquoXYZ CommunicationsrdquoFullName = ldquoXYZ Userrdquo

[Identification]JoinDomain = GONDORDomainAdmin = desktopDomainAdminPassword = eportsew

[Networking]InstalldefaultComponents = no

Chapter 8 Simplify Win2K Desktop Deployment 43

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 44: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

GuiRunOnceThe [GuiRunOnce] section causes the system to run commands after the Mini-Setup Wizard finishesby adding them to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVer-sionRunOnce registry subkey In this case command01 = cwinntsystem32finalsetupvbs runsthe script I created to finish the setup process

UserDataIn the [UserData] section OrgName = ldquoXYZ Communicationsrdquo sets the company name and Full-Name = ldquoXYZ Userrdquo sets the username Enclose the names in quotes if they contain spaces anduse the same username for all computers If you leave these parameters blank the Mini-SetupWizard prompts the user for the names Likewise if the Computername parameter is missing (as itis here) or empty the Mini-Setup Wizard will prompt the user for the name If you set the Com-putername value to the Mini-Setup Wizard will generate a random computer name

IdentificationIn the [Identification] section JoinDomain = GONDOR automatically adds the computer to the NTdomain GONDOR You must supply a username in DomainAdmin = and a password with suffi-cient rights in DomainAdminPassword = to add computers to the domain I created the domainuser account desktop and gave it the Add Workstations to Domain right

The sysprepinf file contains network names and passwords in plain text which might seemlike a big security problem However the Mini-Setup Wizard automatically deletes the folder thatsysprepinf resides in on the target computer

NetworkingIn the [Networking] section setting the InstalldefaultComponents = parameter to no causes theMini-Setup Wizard to leave the network stack alone The master disk image has all the networksettings but if you find that you have machines with different NICs you can set parameters in thissection

Now that the FinalSetupvbs script and the Sysprep utility are ready you need to add them tothe master disk image to prepare it for cloning To add the files to the disk image you must firstcopy them to the computer that you used to make the initial disk image then create a second diskimage I created a batch file named prepsysbat which Listing 3 shows to copy FinalSetupvbs tothe computerrsquos Cwinntsystem32 directory copy the Sysprep utility and supporting files to theSysprep directory on the system driversquos root and run the Sysprep utility When you run Sysprepwith the forceshutdown switch the computer should shut down automatically If it doesnrsquot turnoff the power manually when the hard disk light goes out Donrsquot restart the computer yet

To make a second image of the computerrsquos disk insert a network boot disk as before bootthe computer and connect to the network share Run the disk-imaging software and create thesecond disk image giving it a new name Yoursquoll use the new image to clone workstations Whenyou load this image on a computer and boot the computer the image will perform all the setupsteps Irsquove discussed Save the first image in case you need to make changes

44 Guide to VBScripting

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 45: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

If you do need to modify your master image load the first master image onto a computerMake any necessary changes to the configuration or applications and clean the disk as I instructedearlier Make any necessary changes to the FinalSetupvbs script or sysprepinf file and useprepsysbat to copy the script and the Sysprep files to the computer Prepsysbat will also runSysprep to create a new disk image for cloning

Listing 3Prepsysbat

You can modify a disk that yoursquove prepared with the Sysprep utility but I donrsquot recommenddoing so When you booted the computer for the first time the Mini-Setup Wizard would run andperform setup tasks You would then have to ldquoundordquo the Mini-Setup Wizardrsquos work before makingthe modifications you needed Making a mistake would be too easy

Clone the Master Image to a Workstation To clone the second master disk image to a target workstation you can use one of three methodsUse a network boot disk to boot the workstation then load the disk image from the networkshare use a bootable CD-ROM that contains the image or use a disk duplicator to copy themaster disk to several hard disks at once You might find that you need to use one method forsome workstations and another method for other workstations

I think the most efficient approach is to use a bootable CD-ROM that contains the disk imageThe CD-ROM lets you copy the image to a computer without network connectivity (which the net-work-share approach requires) and without removing the computerrsquos hard disk (which the diskduplicator requires) The CD-ROM (and disk-duplicator) approach also doesnrsquot consume networkbandwidth

After yoursquove loaded the disk image on the target workstation restart the workstation Whenthe computer runs for the first time Sysprep starts the Mini-Setup Wizard which prompts the userfor any information not in the sysprepinf file In my companyrsquos case the computer name was the

REM prepsysbatECHO OFFCLSECHOECHOECHOECHOECHOECHOECHOECHOECHO Preparing disk to run SYSPREPECHOECHOECHOECHOcopy aFINALSETUPVBS cWINNTSYSTEM32MD cSYSPREPcopy asysprepexe csysprepcopy asetupclexe csysprepcopy asysprepinf csysprep

csysprepsysprepexe forceshutdown

Chapter 8 Simplify Win2K Desktop Deployment 45

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting

Page 46: Windows & .NET Magazine's Guide to Automating Administrative Tasks with VBScript

only information the user had to enter The operator used the companyrsquos standard naming conven-tion to give the computer a unique name based on the end userrsquos name department and physicallocation The Mini-Setup Wizard also adds an entry to the HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunOnce registry subkey Win2K will run the FinalSetupvbsscript when someone logs on to the computer the first time

Planning ahead can give network administrators and support staff a painless way to upgradeor reinstall a clientrsquos computer in place in minutes Disk-imaging software WSH scripting andMicrosoftrsquos Sysprep utility are tools anyone deploying desktops should learn to use In the time itwould take you to install and configure a dozen desktops the old-fashioned way you couldmaster these new tools

46 Guide to VBScripting