Microsoft VBScript Step by Step eBook

Add to my manuals
82 Pages

advertisement

Microsoft VBScript Step by Step eBook | Manualzz

● ● ● ● ● ● ● ● ● ● ●

How to access your CD files

The print edition of this book includes a CD. To access the

CD files, go to http://aka.ms/VBSScriptSBS/files, and look for the Downloads tab.

Note: Use a desktop web browser, as files may not be accessible from all ereader devices.

Questions? Please contact: [email protected]

 

Microsoft Press

PUBLISHED BY

Microsoft Press

A Division of Microsoft Corporation

One Microsoft Way

Redmond, Washington 98052-6399

Copyright © 2007 by Ed Wilson

All rights reserved. No part of the contents of this book may be reproduced or transmitted in any form or by any means without the written permission of the publisher.

Library of Congress Control Number: 2006934395

Printed and bound in the United States of America.

1 2 3 4 5 6 7 8 9 QWT 1 0 9 8 7 6

Distributed in Canada by H.B. Fenn and Company Ltd.

A CIP catalogue record for this book is available from the British Library.

Microsoft Press books are available through booksellers and distributors worldwide. For further information about international editions, contact your local Microsoft Corporation office or contact Microsoft

Press International directly at fax (425) 936-7329. Visit our Web site at www.microsoft.com/mspress.

Send comments to [email protected].

Microsoft, Microsoft Press, Active Directory, ActiveX, Excel, MSDN, Visual Basic, Win32, Windows,

Windows NT, Windows Server, and Windows Vista are either registered trademarks or trademarks of

Microsoft Corporation in the United States and/or other countries.

Other product and company names mentioned herein may be the trademarks of their respective owners.

The example companies, organizations, products, domain names, e-mail addresses, logos, people, places, and events depicted herein are fictitious. No association with any real company, organization, product, domain name, e-mail address, logo, person, place, or event is intended or should be inferred.

This book expresses the author’s views and opinions. The information contained in this book is provided without any express, statutory, or implied warranties. Neither the authors, Microsoft Corporation, nor its resellers, or distributors will be held liable for any damages caused or alleged to be caused either directly or indirectly by this book.

Acquisitions Editor: Martin DelRe

Project Editor: Maureen Williams Zimmerman

Copy Editor: Sarah Wales-McGrath

Technical Reviewer: David Holder

Indexer: Jeanne Busemeyer

Body Part No. X13-24158

Dedication

This book is dedicated to my best friend, Teresa.

Contents at a Glance

Part I

Covering the Basics

1

2

Starting from Scratch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Looping Through the Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

3

4

5

Adding Intelligence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

Working with Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

More Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

Part II

Basic Windows Administration

8

9

6

7

10

Working with the File System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

Working with Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

Using WMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187

WMI Continued . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

Querying WMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227

Part III

Advanced Windows Administration

15

16

17

18

11

12

13

14

Introduction to Active Directory Service Interfaces . . . . . . . . . . . . . . . 251

Writing for ADSI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269

Using ADO to Perform Searches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293

Configuring Network Components. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315

Using Subroutines and Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329

Logon Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

Working with the Registry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367

Working with Printers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381 v

vi

Contents at a Glance

Part IV

Scripting Other Applications

19

20

21

Managing IIS 6.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395

Working with Exchange 2003 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407

Troubleshooting WMI Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419

Part V

Appendices

C

D

A

B

E

VBScript Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443

ADSI Documentation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449

WMI Documentation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457

Documentation Standards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463

Special Folder Constants. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469

Table of Contents

Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xvii

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix

Part I

Covering the Basics

1 Starting from Scratch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Running Your First Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

Worker Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

Enhancing Your Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Modifying an Existing Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Modifying the Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

Modifying the Reference Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Modifying the Worker Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Modifying the Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

Exploring a Script: Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

One Step Further: Customizing an Existing Script. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2 Looping Through the Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

Adding Power to Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

For Each…Next . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

Worker Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

For…Next . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

What do you think of this book?

We want to hear from you!

Microsoft is interested in hearing your feedback about this publication so we can continually improve our books and learning resources for you. To participate in a brief online survey, please visit: www.microsoft.com/learning/booksurvey/

vii

viii

Table of Contents

Do While…Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

Do Until…Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

Do…Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

While…Wend. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

Creating Additional Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

Using the For Each…Next Command Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . 51

One Step Further: Modifying the Ping Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

3 Adding Intelligence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

If…Then . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

If…Then…ElseIf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

If…Then…Else. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

Select Case. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

Modifying CPUType.vbs Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

One Step Further: Modifying ComputerRoles.vbs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

4 Working with Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

Passing Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

Command-Line Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

Making the Change. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

Running the Command Prompt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

No Arguments? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

Creating a Useful Error Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

Using Multiple Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

Table of Contents ix

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

Tell Me Your Name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

Reasons for Named Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

Making the Change to Named Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

Running a Script with Named Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

Working with Arrays. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

Moving Past Dull Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

What Does UBound Mean? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

Two-Dimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

Mechanics of Two-Dimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

Passing Arguments Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

One Step Further: Building Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

5 More Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

Strings and Arrays. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

Parsing Passed Text into an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

Worker Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

Parsing Passed Text. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

Worker Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

Working with Dictionaries. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

Understanding the Dictionary Object. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

Adding Items to the Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

Using Basic InStr Step-by-Step Exercises. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

One Step Further: Creating a Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

x

Table of Contents

Part II

Basic Windows Administration

6 Working with the File System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

Creating the File System Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

File It Under Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

File Properties. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

File Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

Implementing the Attributes Property. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

Setting File Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

Creating Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

Writing to a Text File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

Determining the Best Way to Write to a File. . . . . . . . . . . . . . . . . . . . . . . . . . . 150

Overwriting a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

Verifying a File Exists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156

Creating Files Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161

One Step Further: Creating a Log File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

7 Working with Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

Working with Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

Creating the Basic Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

Creating Multiple Folders. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

Worker Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

Output Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

Automatic Cleanup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

Deleting a Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

Deleting Multiple Folders. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173

Binding to Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

Does the Folder Exist? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175

Copying Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

Moving Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

Creating Folders Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182

One Step Further: Deleting Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

Table of Contents xi

8 Using WMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187

Leveraging WMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187

Understanding the WMI Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

Working with Objects and Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189

Digging Deeper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

Listing WMI Providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

Working with WMI Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

Viewing Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197

Working with WMI Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

Querying WMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

Retrieving Hotfix Information Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . 204

One Step Further: Echoing the Time Zone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205

9 WMI Continued . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

Alternate Ways of Configuring the WMI Moniker. . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

Accepting Defaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

Moniker Security Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214

WbemPrivilege Has Its Privileges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215

Using the Default WMI Moniker Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . 220

Invoking the WMI Moniker to Display the Machine Boot Configuration . . . . . . . . 221

Including Additional Security Permissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222

One Step Further: Using Win32_Environment and VBScript to Learn About WMI 224

10 Querying WMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227

Tell Me Everything About Everything! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

Selective Data from All Instances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230

Selecting Multiple Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

Choosing Specific Instances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

Using an Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238

Where Is the Where Clause? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241

xii

Table of Contents

Writing an Informative WMI Script Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . 244

One Step Further: Obtaining More Direct Information . . . . . . . . . . . . . . . . . . . . . . . . 245

Part III

Advanced Windows Administration

11 Introduction to Active Directory Service Interfaces . . . . . . . . . . . . . . . 251

Working with ADSI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253

LDAP Names. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255

Worker Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255

Output Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257

Creating Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

Worker Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

Output Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

Creating OUs Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263

One Step Further: Creating Multi-Valued Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

12 Writing for ADSI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269

Working with Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269

General User Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272

Worker Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272

Output Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273

Modifying the Address Tab Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275

Worker Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275

Output Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

Modifying Terminal Server Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283

Deleting Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

Deleting Users Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

One Step Further: Using the Event Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290

13 Using ADO to Perform Searches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293

Connecting to Active Directory to Perform a Search . . . . . . . . . . . . . . . . . . . . . . . . . . 293

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296

Table of Contents xiii

Creating More Effective Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297

Searching for Specific Types of Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301

Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301

What Is Global Catalog? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303

Creating an ADO Query into Active Directory Step-by-Step Exercises . . . . . . . . . . 311

One Step Further: Controlling Script Execution While

Querying Active Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312

14 Configuring Network Components. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315

WMI and the Network . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315

Making the Connection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318

Changing the TCP/IP Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321

Merging WMI and ADSI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322

Win32_NetworkAdapterConfiguration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323

Using WMI to Assign Network Settings Step-by-Step Exercises . . . . . . . . . . . . . . . . 325

One Step Further: Combining WMI and ADSI in a Script . . . . . . . . . . . . . . . . . . . . . 326

15 Using Subroutines and Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329

Working with Subroutines. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329

Calling the Subroutine. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331

Creating the Subroutine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332

Creating Users and Logging Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335

Worker Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336

Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336

Working with Functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341

Using ADSI and Subs, and Creating Users Step-by-Step Exercises . . . . . . . . . . . . . . 343

One Step Further: Adding a Logging Subroutine . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345

xiv

Table of Contents

16 Logon Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

Working with IADsADSystemInfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

Using Logon Scripts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351

Deploying Logon Scripts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355

Worker Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357

Output Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358

Adding a Group to a Logon Script Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . 360

One Step Further: Adding Logging to a Logon Script . . . . . . . . . . . . . . . . . . . . . . . . . 362

17 Working with the Registry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367

First You Back Up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367

Creating the WshShell Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368

Setting the comspec Variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368

Defining the Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369

Connecting to the Registry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372

Unleashing the Power of the StdRegProv Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372

Creating Registry Keys. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375

Writing to the Registry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375

Deleting Registry Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376

Reading the Registry Using WMI Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . 377

One Step Further: Creating Registry Keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378

18 Working with Printers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381

Working with Win32_Printer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381

Obtaining the Status of Printers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382

Header Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384

Worker Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384

Output Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385

Table of Contents xv

Creating a Filtered Print Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387

Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387

Monitoring Print Queues. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389

Monitoring Print Jobs Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389

One Step Further: Checking the Status of a Print Server . . . . . . . . . . . . . . . . . . . . . . 391

Part IV

Scripting Other Applications

19 Managing IIS 6.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395

Locating the WMI Classes for IIS 6.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395

CIM_ManagedSystemElement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395

CIM_Setting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395

IIsStructuredDataClass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

CIM_Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

CIM_ElementSetting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

Using MicrosoftIISv2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

Making the Connection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399

Creating a Web Site . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

Worker and Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402

Backing Up the Metabase Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 403

One Step Further: Importing the Metabase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404

20 Working with Exchange 2003 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407

Working with the Exchange Provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407

Connecting to MicrosoftExchangeV2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408

The Exchange_QueueSMTPVirtualServer Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409

Header Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409

Reference Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410

Worker Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410

Output Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410

Exchange Public Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411

xvi

Table of Contents

Exchange_FolderTree. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413

Using the Exchange_Logon Class Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . 414

One Step Further: Using the Exchange_Mailbox Class . . . . . . . . . . . . . . . . . . . . . . . . . 416

21 Troubleshooting WMI Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419

Identifying the Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419

Spotting Common Sources of Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419

Testing the Local WMI Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420

Using the WMI Control Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420

Using the Scriptomatic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422

Examining the Status of the WMI Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422

Using WBEMtest.exe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423

Testing Remote WMI Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424

Remotely Using the WMI Control Tool. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424

Testing Scripting Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425

Obtaining Diagnostic Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426

Enabling Verbose WMI Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427

Examining the WMI Log Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428

Using the Err Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429

Using MofComp.exe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430

Using WMIcheck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431

General WMI Troubleshooting Steps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432

Working with Logging Step-by-Step Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433

One Step Further: Compiling MOF Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437

Part V

Appendices

Appendix A: VBScript Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443

Appendix B: ADSI Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449

Appendix C: WMI Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457

Appendix D: Documentation Standards. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463

Appendix E: Special Folder Constants. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469

What do you think of this book?

We want to hear from you!

Microsoft is interested in hearing your feedback about this publication so we can continually improve our books and learning resources for you. To participate in a brief online survey, please visit: www.microsoft.com/learning/booksurvey/

Acknowledgments

The process of writing a technical book is more a matter of collaboration, support, and team work, than a single wordsmith sitting under a shade tree with parchment and pen. It is amaz­ ing how many people know about your subject after you begin the process.

I am very fortunate to have assembled a team of friends and well wishers over the past few years to assist, cajole, exhort, and inspire the words to appear. First and foremost is my wife

Teresa. She has had the great fortune of reading 10 technical books in the past 11 years, while at the same time putting up with the inevitable encroachment of deadlines on our otherwise well timed vacation schedule. Claudette Moore of the Moore Literary Agency has done an awesome job of keeping me busy through all her work with the publishers. Martin DelRe at

Microsoft Press has been a great supporter of scripting technology, and is a great person to talk to. Maureen Zimmerman, also of Microsoft Press, has done a great job of keeping me on schedule, and has made numerous suggestions to the improvement of the manuscript.

xvii

Introduction

Network administrators and consultants are confronted with numerous mundane and timeconsuming activities on a daily basis. Whether it is going through thousands of users in Active

Directory Users and Computers to grant dial-in permissions to a select group, or changing profile storage locations to point to a newly added network server, these everyday tasks must be completed. In the enterprise space, the ability to quickly write and deploy a Microsoft

Visual Basic Script (VBScript) will make the difference between a task that takes a few hours and one that takes a few weeks.

As an Enterprise Consultant for Microsoft Corporation, I am in constant contact with some of the world’s largest companies that run Microsoft software. The one recurring theme I hear is,

“How can we effectively manage thousands of servers and tens of thousands of users?” In some instances, the solution lies in the employment of specialized software packages—but in the vast majority of the cases, the solution is a simple VBScript.

In Microsoft Windows Server 2003, enterprise manageability was one of the design goals, and

VBScript is one path to unlocking the rich storehouse of newly added features. Using the tech­ niques outlined in Microsoft VBScript Step by Step, anyone can begin crafting custom scripts within minutes of opening these pages. I’m not talking about the traditional Hello World script—I’m talking about truly useful scripts that save time and help to ensure accurate and predictable results.

Whereas in the past scripting was somewhat hard to do, required special installations of vari­ ous implementations, and was rather limited in its effect, with the release of Microsoft Win­ dows XP, Windows Server 2003, and Windows Vista, scripting is coming into its own. This is really as it should be. However, most administrators and IT professionals do not have an understanding of scripting because in the past scripting was not a powerful alternative for platform management.

However, in a large enterprise, it is a vital reality that one simply cannot perform management from the GUI applications because it is too time-constraining, too error prone, and, after a while, too irritating. Clearly there needs to be a better way, and there is. Scripting is the answer.

A Practical Approach to Scripting

Microsoft VBScript Step by Step will equip you with the tools to automate setup, deployment, and management of Microsoft Windows 2003 networks via the various scripting interfaces contained within the product. In addition, it will provide you with an understanding of a select number of VBScripts adaptable to your own unique environments. This will lead you into an awareness of the basics of programming through modeling of fundamental techniques.

xix

xx

Introduction

The approach I take to teaching you how to use VBScript to automate your Windows 2003 servers is similar to the approach used in some executive foreign language schools. You’ll learn by using the language. In addition, concepts are presented not in a dry academic fash­ ion, but in a dynamic, real-life manner. When a concept is needed to accomplish something, it is presented. If a topic is not useful for automating network management, I don’t bring it forward.

This is a practical, application-oriented book, so the coverage of VBScript, Windows Scripting

Host, Active Directory Service Interfaces (ADSI), and Windows Management Instrumentation

(WMI) is not exceedingly deep. This is not a reference book; it is a tutorial, a guide—a spring­ board for ideas, perhaps—but not an encyclopedia.

Is This Book for Me?

Microsoft VBScript Step by Step is aimed at several audiences, including:

Windows networking consultants

Anyone desiring to standardize and automate the installation and configuration of .NET networking components.

Windows network administrators

Anyone desiring to automate the day-to-day management of Windows .NET networks.

Windows Help Desk staff

connected desktops.

Anyone desiring to verify configuration of remotely

Microsoft Certified Systems Engineers (MCSEs) and Microsoft Certified Trainers (MCTs)

Although scripting is not a strategic core competency within the MCP program, a few questions about scripting do crop up from time to time on various exams.

General technical staff

Anyone desiring to collect information, configure settings on

Windows XP machines, or implement management via WMI, WSH, or WBEM.

Power users

Anyone wishing to obtain maximum power and configurability of their

Windows XP machines either at home or in an unmanaged desktop workplace environment.

Outline of This Book

This book is divided into four parts, each covering a major facet of scripting. The following sections describe these parts.

Part I: Covering the Basics

Okay, so you’ve decided you need to learn scripting. Where do you begin? Start here in Part I!

In Chapter 1, “Starting From Scratch,” you learn the basics: what a script is, how to read it, and how to write it. Once you move beyond using a script to figure out what your IP address is and print it to a file, you need to introduce some logic into the script, which you do in Chapter 2 through Chapter 5. You’ll learn how to introduce conditions and add some intelligence to

Introduction xxi

allow the script to check some stuff, and then based upon what it finds, do some other stuff.

This section concludes by looking at troubleshooting scripts. I’ve made some mistakes that you don’t need to repeat! Here are the chapters in Part I:

Chapter 1, “Starting from Scratch”

Chapter 2, “Looping Through The Script”

Chapter 3, “Adding Intelligence”

Chapter 4, “Working with Arrays”

■ Chapter 5, “More Arrays”

Part II: Basic Windows Administration

In Part II, you dig deep into VBScript and WMI and really begin to see the power you can bring to your automation tasks. In working with the file system, you see how to use the file system object to create files, delete files, and verify the existence of files. All these basic tasks provide loads of flexibility for your scripts. Next, you move on to working with folders, learning how to use VBScript to completely automate the creation of folders and files on your servers and users’ workstations. In the last half of Part II, you get an in-depth look at the power of WMI when it is combined with the simplicity and flexibility of VBScript. Here are the chapters in Part II:

Chapter 6, “Working with the File System”

Chapter 7, “Working with Folders”

Chapter 8, “Using WMI”

Chapter 9, “WMI Continued”

Chapter 10, “Querying WMI”

Part III: Advanced Windows Administration

This section will shave at least four points off your golf handicap because you’ll get to play an extra 18 holes a week due to the time you’ll save! At least three things are really painful when it comes to administering Windows servers: all those click, click, and save motions; all the time spent waiting for the screen to refresh; and loosing your place in a long list of users.

Guess what? In this section, some of that pain is relieved. When Human Resources hires 100 people, you tell them to send you a spreadsheet with the new users, and then use a script to create those users. It takes 2 minutes instead of 2 hours. (Dude, that’s the front nine!) In addi­ tion to saving time, scripting your administrative tasks reduces the likelihood of errors. If you have to set a particular set of access control lists on dozens of folders, a script is the only way to ensure all the flags are set correctly. Here are the chapters in Part III:

Chapter 11, “Introduction to Active Directory Service Interfaces”

Chapter 12, “Writing for ADSI”

xxii

Introduction

Chapter 13, “Using ADO to Perform Searches”

Chapter 14, “Configuring Networking Components”

Chapter 15, “Using Subroutines and Functions”

Chapter 16, “Logon Scripts”

Chapter 17, “Working with the Registry”

Chapter 18, “Working with Printers”

Part IV: Scripting Other Applications

Once you learn how to use WMI and VBScript to automate Windows Server 2003, the logical question is, “What else can I do?” Well, with the latest version of Microsoft Exchange and

Internet Information Services (IIS), the answer is, “Quite a lot.” So in this part of the book, you look at using WMI and VBScript to automate other applications.

In IIS 6.0, nearly everything that can be configured via GUI tools can also be scripted. This enables the Web administrator to simplify management and to also ensure repeatable config­ uration of the Web sites from a security perspective.

In Exchange administration, many routine tasks can be simplified by using VBScript. In Part

IV, you look at how to leverage the power of VBScript to simplify user management, to config­ ure and administer Exchange, and to troubleshoot some of the common issues confronting the enterprise Exchange administrator. The chapters in Part IV are as follows:

Chapter 19, “Managing IIS 6.0”

Chapter 20, “Working with Exchange 2003”

Chapter 21, “Troubleshooting WMI Scripting"

Part V: Appendices

The appendices in this book are not the normal “never read” stuff. Indeed, you will find your­ self referring again and again to these five crucial documents. In Appendix A you will find lots of ideas for further work in developing your mastery of VBScript. Appendix B will save you many hours of searching for the “special names” that unlock the power of ADSI scripting.

Appendix C helps you find the special WMI namespaces that enable you to perform many cool “tricks” in your scripting. And last but certainly not least is Appendix D, which contains my documentation “cheat sheet.” Actually, you will want to read it rather early in your script­ ing career. Appendix E contains the Special Folder Constants, which, as you will see in the very first script in the book, can provide easy access to some of the most vital folders on your workstation!

Appendix A, “VBScript Documentation”

Appendix B, “ADSI Documentation”

Introduction xxiii

Appendix C, “WMI Documentation”

Appendix D, “Documentation Standards”

Appendix E, “Special Folder Constants”

Finding Your Best Starting Point

This book will help you add essential skills for using VBScript to automate your Windows environment. You can use this book if you are new to scripting, new to programming, or switching from another scripting language. The following table will assist you in picking the best starting point in the book.

If you are

New to programming

New to VBScript

Follow these steps

Install the practice files as described in the section “Installing the Practice Files on Your

Computer” later in this Introduction.

Learn the basic skills for using VBScript by working through Chapters 1-7 in order.

Install the practice files as described in the section “Installing the Practice Files on Your

Computer” later in this Introduction.

Skim through Chapter 1, making sure you pay attention to the section on creating objects.

Skim Chapter 2 and Chapter 3.

Complete Chapter 4 through Chapter 7 in order.

Experienced with VBScript but are interested in Install the practice files as described in the using WMI section “Installing the Practice Files on Your

Computer” later in this Introduction.

Skim Chapter 4, paying attention to handling arrays.

Work through Chapters 8-10 in order.

Complete Chapter 14.

About the Companion CD

The CD accompanying this book contains additional information and software components, including the following files:

Sample Files

The chapter folders contain starter scripts, some text files, and completed solutions for each of the procedures contained in this book. In addition, each of the scripts discussed in the book is contained in the folder corresponding to the chapter number. For instance, in Chapter 1 we talk about enumerating disk drives on a com­

xxiv

Introduction

puter system. The script that makes up the bulk of our discussion around that topic is contained in the \My Documents\Microsoft Press\VBScriptSBS\ch01 folder. You’ll also find many bonus scripts in the chapter folders. In addition to the sample files in the chapter folders, the CD includes a Templates folder, a Resources folder, a Supplemental folder, and a Utilities folder. These folders contain dozens of my favorite scripts and util­ ities I have written over the last several years to solve literally hundreds of problems. You will enjoy playing around with these and incorporating them into daily scripting tasks.

For example, in the Templates folder you will find my WMITemplate.vbs script. By using it as a starter, you can write a custom WMI script in less than five seconds. By using the

ADOSearchTemplate.vbs script as a starter, you can write a script that returns all the users in a particular OU in less than three seconds. In the Utilities folder you will find, for example, a script that converts bytes into kilobytes, megabytes, or gigabytes depend­ ing on the largest whole number that can be so created.

eBook

You can view an electronic version of this book on screen using Adobe Acrobat

Reader. For more information, see the Readme.txt file included in the root folder of the

Companion CD.

Tools and Resources

Additional tools and resources to make scripting faster and easier:

Scriptomatic 2.0, Tweakomatic, EZADScriptomatic, WMI Admin Tools, WMI CodeCre­ ator, WMI Diag.

Installing the Practice Files on Your Computer

Follow these steps to install the practice files on your computer so that you can use them with the exercises in this book.

1. Remove the companion CD from the package inside this book and insert it into your

CD-ROM drive.

Note

An end user license agreement should open automatically. If this agreement does not appear, open My Computer on the desktop or Start menu, double-click the icon for your CD-ROM drive, and then double-click StartCD.exe.

2. Review the end user license agreement. If you accept the terms, select the accept option

and then click Next.

A menu will appear with options related to the book.

3. Click Install Code Samples.

4. Follow the instructions that appear.

The code samples are installed to the following location on your computer:

My Documents\Microsoft Press\VBScriptSBS\

Introduction xxv

Uninstalling the Practice Files

Follow these steps to remove the practice files from your computer.

1. In the Control Panel, open Add Or Remove Programs.

2. From the list of Currently Installed Programs, select Microsoft VBScript Step by Step.

3. Click Remove.

4. Follow the instructions that appear to remove the code samples.

System Requirements

Special Folder Constants

Minimum 233 MHz in the Intel Pentium/Celeron family or the AMD k6/Atholon/

Duron family

64 MB memory

1.5 GB available hard disk space

Display monitor capable of 800 x 600 resolution or higher

CD-ROM drive or DVD drive

Microsoft Mouse or compatible pointing device

Windows Server 2003,Windows XP, or Windows Vista

The MSI Provider installed on Windows Server 2003 (required for some of the WMI procedures)

■ Microsoft Office Excel or Excel Viewer

Technical Support

Every effort has been made to ensure the accuracy of this book and the contents of the com­ panion CD-ROM. Microsoft Press provides corrections for books through the World Wide

Web at http:// www.microsoft.com/learning/support.

To connect directly with the Microsoft Press Knowledge Base and enter a query regarding a question or an issue that you might have, go to http://www.microsoft.com/learning/support

/search.asp.

If you have comments, questions, or ideas regarding this book or the companion CD-ROM, please send them to Microsoft Press using either of the following methods:

E-mail:

[email protected]

xxvi

Introduction

Postal Mail:

Microsoft Press

Attn: Editor, Microsoft VBScript Step by Step

One Microsoft Way

Redmond, WA 980526399

Please note that product support is not offered through the preceding addresses.

For additional support information regarding this book and the CD-ROM (including answers to commonly asked questions about installation and use), visit the Microsoft Press Technical

Support Web site at www.microsoft.com/learning/support/books/. For support information regarding Microsoft software, please connect to http://support.microsoft.com.

Chapter 3

Adding Intelligence

Before You Begin

To successfully complete this chapter, you need to be familiar with the following concepts, which were presented in Chapters 1 and 2:

■ Declaring variables

■ Basic error handling

■ Connecting to the file system object

■ Using For Each…Next

■ Using Do While

After completing this chapter, you will be able to:

■ Use If…Then

■ Use If…Then…ElseIf

■ Use If…Then…Else

■ Use Select Case

■ Use intrinsic constants

If…Then

If…Then is one of those programming staples (like fried chicken and mashed potatoes are sta­ ples in the southern United States). What’s nice about If…Then is that it makes sense. We use this kind of logic all the time.

The basic operation is diagrammed here:

If

If

condition

store is open

Then

Then

action

buy chicken

The real power of If…Then comes into play when combined with tools such as those we looked at in Chapter 2, “Looping Through the Script.” If…Then is rarely used by itself. Although you could have a script such as IfThen.vbs, you wouldn’t find it very valuable.

55

56

Part I Covering the Basics

IfThen.vbs

On Error Resume Next

Const a = 2

Const b = 3

Const c = 5

WScript.Echo(c)

End If

In this script three constants are defined: a, b, and c. We then sum the numbers and evaluate the result by using the If…Then statement. There are three important elements to pay attention to in implementing the If…Then construct:

■ The If and the Then must be on the same line

■ The action to be taken must be on the next line

■ You must end your If…Then statement by using End If

If any of these elements are missing or misplaced, your If…Then statement generates an error.

Make sure you remember that End If is two words, and not one word as in some other pro­ gramming languages. If you do not see an error and one of these elements is missing, make sure you have commented out On Error Resume Next.

Now that you have the basic syntax down pat, let’s look at the following more respectable and useful script, named GetComments.vbs, which is in the folder \My Documents\Microsoft

Press\VBScriptSBS\ch03. If you put lots of descriptive comments in your Microsoft Visual

Basic, Scripting Edition (VBScript) scripts, Then GetComments.vbs pulls them out and writes them into a separate file. This file can be used to create a book of documentation about the most essential scripts you use in your network. In addition, If you standardize your documen­ tation procedures, Then the created book will require very little touch-up work when you are finished. (OK, I’ll quit playing If…Then with you. Let’s look at that code, which is described in the next few sections.)

GetComments.vbs

Option Explicit

On Error Resume Next

Dim scriptFile

Dim commentFile

Dim objScriptFile

Dim objFSO

Dim objCommentFile

Dim strCurrentLine

Dim intIsComment

Const ForReading = 1

Const ForWriting = 2 scriptFile = "displayComputerNames.vbs" commentFile = "comments.txt"

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objScriptFile = objFSO.OpenTextFile _

(scriptFile, ForReading)

Chapter 3 Adding Intelligence

Set objCommentFile = objFSO.OpenTextFile(commentFile, _

ForWriting, TRUE)

Do While objScriptFile.AtEndOfStream <> TRUE strCurrentLine = objScriptFile.ReadLine intIsComment = Instr(1,strCurrentLine,"'")

If intIsComment > 0 Then objCommentFile.Write strCurrentLine & VbCrLf

End If

Loop

WScript.Echo("script complete") objScriptFile.Close objCommentFile.Close

Just the Steps

To implement If…Then

1. On a new line in the script, type If some condition Then.

2. On the next line, enter the command you want to invoke.

3. On the next line, type End If.

57

Header Information

The first few lines of the GetComments.vbs script contain the header information. We use

Option Explicit to force us to declare all the variables used in the script. This helps to ensure that you spell the variables correctly as well as understand the logic. On Error Resume Next is rudimentary error handling. It tells VBScript to go to the next line in the script when there is an error. There are times, however, when you do not want this behavior, such as when you copy a file to another location prior to performing a delete operation. It would be disastrous if the copy operation failed but the delete worked.

After you define the two constants, you define the variables. Listing variables on individual lines makes commenting the lines in the script easier, and the commenting lets readers of the script know why the variables are being used. In reality, it doesn’t matter where you define variables, because the compiler reads the entire script prior to executing it. This means you can spread constant and variable declarations all over the script any way you want—such an approach would be hard for humans to read, but it would make no difference to VBScript.

Reference Information

In the Reference information section of the script, you define constants and assign values to several of the variables previously declared.

The lines beginning with Const of the GetComments.vbs script define two constants,

ForReading and ForWriting, which make the script easier to read. (You learned about constants in Chapter 2.) You’ll use them when you open the DisplayComputerNames.vbs file and the comments.txt file from the ch03 folder on the CD. You could have just used the numbers 1 and 2 in your command and skipped the two constants; however, someone reading the script

58

Part I Covering the Basics

needs to know what the numbers are doing. Because these values will never change, it is more efficient to define a constant instead of using a variable. This is because the computer knows that you will only store two small numbers in these two constants. On the other hand, if we declared these two as variables, then the operating system would need to reserve enough memory to hold anything from a small number to an entire object. These varients (as they are called) are easy on programmers, but are wasteful of memory resources. But it is, after all, just a scripting language. If we were really concerned about efficiency, and conservation of resources, we would be writing in C++.

The name of the file you are extracting comments from is stored in the variable scriptFile. By using the variable in this way it becomes easy to modify the script later so that you can either point it to another file or make the script read all the scripts in an entire folder. In addition, you could make the script use a command-line option that specifies the name of the script to parse for comments. However, by assigning a variable to the script file name, you make all those options possible without a whole lot of rewriting. This is also where you name the file used to write the comments into—the aptly named comments.txt file.

Quick Check

Q. Is it permissible to have If on one line and Then on a separate line?

A. No. Both If and Then must be on the same logical line. They can be on separate physical lines if the line continuation character (_) is used. Typically, If is the first word and Then is the last command on the line.

Q. If the Then clause is on a separate logical line from the If…Then statement, what com­ mand do you use?

A. End If. The key here is that End If consists of two words, not one.

Q. What is the main reason for using constants?

A. Constants have their value set prior to script execution, and therefore their value does not change during the running of the script.

Q. What are two pieces of information required by the OpenTextFile command?

A. OpenTextFile requires both the name of the file and whether you want to read or write.

Worker and Output Information

The Worker and Output information section is the core engine of the script, where the actual work is being done. You use the Set command three times, as shown here:

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objScriptFile = objFSO.OpenTextFile _

(scriptFile, ForReading)

Set objCommentFile = objFSO.OpenTextFile(commentFile, _

ForWriting, TRUE)

Chapter 3 Adding Intelligence

59

Regarding the first Set command, you’ve seen objFSO used several times already in Chapter 2.

objFSO is a variable name, which we routinely assign to our connection to the file system, that allows us to read and write to files. You have to create the file system object object (as it is tech­ nically called) to be able to open text files.

The second Set command uses our objScriptFile variable name to allow us to read the Display-

ComputerNames.vbs file. Note that the OpenTextFile command requires only one piece of information: the name of the file. VBScript will assume you are opening the file for reading if you don’t include the optional file mode information. We are going to specify two bits of infor­ mation so that the script is easier to understand:

■ The name of the file

■ How you want to use the file—that is, read or write to it

By using variables for these two parts of the OpenTextFile command, you make the script much more flexible and readable.

The third Set command follows the same pattern. You assign the objCommentFile variable to whatever comes back from the openTextFile command. In this instance, however, you write to the file instead of read from it. You also use variables for the name of the comment file and for the option used to specify writing to the file.

The GetComments.vbs script reads each line of the DisplayComputerNames.vbs file and checks for the presence of a single quotation mark ('). When the single quotation mark is present, the script writes the line that contains that character out to the comments.txt file.

A closer examination of the Worker and Output information section of the GetComments.vbs script reveals that it begins with Do While…Loop, as shown here:

Do While objScriptFile.AtEndOfStream <> TRUE strCurrentLine = objScriptFile.ReadLine intIsComment = InStr(1,strCurrentLine,"'")

If intIsComment > 0 Then objCommentFile.Write strCurrentLine & vbCrLf

End If

Loop

WScript.Echo("script complete") objScriptFile.Close objCommentFile.Close

You first heard about the Do While statement in Chapter 2. ObjScriptFile contains a textStream

Object. This object was created when we used the openTextFile method from the fileSystem

Object. The textStreamObject has a property that is called atEndOfStream. As long as you aren’t at the end of the text stream, the script reads the line of text and sees whether it contains a sin­ gle quotation mark. AtEndOfStream is a property. It describes a physical location. Of course, we do not know where AtEndOfStream is located, so we use Do While to loop around until it finds the end of the stream.

60

Part I Covering the Basics

To check for the presence of the <'> character, you use the InStr function, just as discussed in

Chapter 2. The InStr function returns a zero when it does not find the character; when it does find the character, it returns a number representing the location in the line of text that the character was found.

If InStr finds the <'> character within the line of text, the variable intIsComment holds a num­ ber that is larger than zero. Therefore, you use the If…Then construct, as shown in the follow­ ing code, to write out the line to the comments.txt file:

If intIsComment > 0 Then objCommentFile.Write strCurrentLine & vbCrLf

End If

Notice that the condition to be evaluated is contained within If…Then. If the variable intIsCom­

ment is larger than zero, you take the action on the next line. Here you use the Write command to write out the current line of the DisplayComputerNames.vbs file.

Use the Timer function to see how long the script runs

1. Open the GetComments.vbs script in Microsoft Notepad or the script editor of your

choice.

2. Save the script as YourNameGetCommentsTimed.vbs.

3. Declare two new variables: startTime and endTime. Put these variables at the bottom of

your list of variables, and before the constants. It will look like:

Dim startTime, endTime

4. Right before the line where you create the FilesystemObject and set it to the objFSO vari­

able, assign the value of the Timer function to the startTime variable. It will look like the following: startTime = Timer

5. Right before the script complete line, assign the value of timer to the endTime variable. It

will look like: endTime = Timer

6. Now edit the script complete line to include the time it took to run. Use the ROUND func­

tion to round off the time to two decimal places. The line will look like the following:

WScript.Echo "script complete. " & round(endTime-startTime, 2)

7. Save and run your script. Compare your script with GetCommentsTimed.vbs in

\My Documents\Microsoft Press\VBScriptSBS\ch03 if desired.

Chapter 3 Adding Intelligence

61

Intrinsic Constants

You use the vbCrLf command to perform what is called a carriage return and line feed.

vbCrLf is an intrinsic constant, which means that it is a constant that is built into

VBScript. Because intrinsic constants are built into VBScript, you don’t need to define them as you do regular constants. You’ll use other intrinsic constants as you continue to develop scripts in VBScript language in later chapters.

vbCrLf has its roots in the old-fashioned manual typewriter. Those things had a handle on the end that rolled the plate up one or two lines (the line feed) and then repositioned the type head (the carriage return). Like the typewriter handle, the vbCrLf command positions the text to the first position on the following line. It’s a very useful command for formatting text in both dialog boxes and text files. The last line in our If…Then con­ struct is the End If command. End If tells VBScript that we’re finished using the If…Then command. If you don’t include End If, VBScript complains with an error.

The Platform SDK documents many other intrinsic constants that we can use with

VBScript. Besides vbCrLf, the one I use the most is vbTab, which will tab over the default tab stop. It is helpful for indenting output. You can look up others in the Scripts56.chm file included in the Resources folder on the CD-ROM by searching for “intrinsic constants.”

After using End If, you have the Loop command on a line by itself. The Loop command belongs to the Do While construct that began the Worker and Output information section. Loop sends the script execution back to the Do While line. VBScript continues to loop through, reading the text file and looking for ' marks, as long as it doesn’t reach the end of the text stream.

When VBScript reaches the end of the text stream from the DisplayComputerNames script, a message displays saying that you’re finished processing the script. This is important, because otherwise there would be no indication that the script has concluded running. You then close your two files and the script is done. In reality, you don’t need to close the files because they will automatically close once the script exits memory, but closing the files is good practice and could help to avoid problems if the script hangs.

Making a decision using If…Then

1. Open Notepad or the script editor of your choice. Navigate to the blankTemplate.vbs

template in the \My Documents\Microsoft Press\VBScriptSBS\Templates directory.

2. Save the template as YourNameConvertToGig.vbs.

3. On the first non-commented line, type Option Explicit.

4. On the next line, declare the variable intMemory.

5. The next line begins the Reference section. Assign the value 120,000 to the intMemory

variable. It will look like the following: intMemory = 120000

62

Part I Covering the Basics

6. Use the formatNumber function to remove all but the last two digits after the decimal

place. It will look like the following: intMemory = formatNumber(intMemory/1024)

7. If the value of intMemory is greater than 1024, then we want to convert it to gigabytes,

print out the value, and then exit the script. We will use formatNumber to clean up the trailing decimal places. Your code will look like the following:

If intMemory > 1024 Then intMemory = formatNumber(intMemory/1024) & " Gigabytes"

WScript.Echo intMemory

WScript.quit

End If

8. Under the If…Then End If construction, we assign the value to intMemory, as seen below.

intMemory = intMemory & " Megabytes"

9. Then we echo out the value of intMemory, as seen below:

WScript.Echo intMemory

10. Save and run the script. Compare your results to ConvertToGig.vbs in the folder \My

Documents\Microsoft Press\VBScriptSBS\ch03.

If…Then…ElseIf

If…Then…ElseIf adds some flexibility to your ability to make decisions by using VBScript.

If…Then enables you to evaluate one condition and take action based on that condition. By adding ElseIf to the mixture, you can make multiple decisions. You do this in the same way you did it using the If…Then command. You start out with an If…Then on the first line in the

Worker information section, and when you are finished, you end the If…Then section with End

If. If you need to make additional evaluations, add a line with ElseIf and the condition.

Just the Steps

To Use If…Then…ElseIf

1. On a new line in the script, type If some condition Then.

2. On the next line, enter the command you want to invoke.

3. On the next line, type ElseIf and the new condition to check, and end the line with Then.

4. On the next line, enter the command you want to invoke when the condition on the

ElseIf line is true.

5. Repeat steps 3 and 4 as required.

6. On the next line, type End If.

Chapter 3 Adding Intelligence

63

You can have as many ElseIf lines as you need; however, if you use more than one or two, the script can get long and confusing. A better solution to avoid a long script is to convert to a

Select Case type of structure, which is covered later in this chapter in the “Select Case” section.

Using the message box msgBox.vbs

1. Open Notepad or the script editor of your choice.

2. Define four variables that will hold the following: the title of the message box, the

prompt for the message box, the button configuration, and the return code from the message box. The variables I used are strPrompt, strTitle, intBTN, intRTN. They are declared as follows:

Dim strPrompt

Dim strTitle

Dim intBTN

Dim intRTN

3. Assign values to the first three variables. strPrompt is what you want to display to the

user. The title will appear at the top of the message box. The value contained in strTitle will appear at the top of the message box. The variable intBTN is used to control the style of the buttons you want displayed. strPrompt = "Do you want to run the script?" strTitle = "MsgBOX DEMO" intBTN = 3 '4 is yes/no 3 is yes/no/cancel

4. Now write the code to display the message box. To do this, we will use intRTN to capture

the return code from pressing the button. We will use each of our three message box variables as well and the msgBox function. The line of code looks like the following: intRTN = MsgBox(strprompt,intBTN,strTitle)

5. If you run the script right now, it will run and display a message box, but you are not

evaluating the outcome. To do that, we will use If…Then…Else to evaluate the return code. It will look like the following:

If intRTN = vbYes Then

WScript.Echo "yes was pressed"

ElseIf intRTN = vbNo Then

WScript.Echo "no was pressed"

ElseIf intRTN = vbCancel Then

WScript.Echo "cancel was pressed"

Else

WScript.Echo intRTN & " was pressed"

End If

6. Save the script as YourNameMsgBox.vbs and run it. It should tell you which button was

pressed from the message box. You would then tie in the code to the appropriate button instead of just echoing the return values. Compare your code with msgBox.vbs in the folder \My Documents\Microsoft Press\VBScriptSBS\ch03 if required.

64

Part I Covering the Basics

Let’s examine a script that uses If…Then…ElseIf to detect the type of central processing unit

(CPU) that is installed in a computer. Here is the CPUType.vbs script from the ch03 folder on the CD.

CPUType.vbs

Option Explicit

On Error Resume Next

Dim strComputer

Dim cpu

Dim wmiRoot

Dim objWMIService

Dim ObjProcessor strComputer = "." cpu = "win32_Processor='CPU0'" wmiRoot = "winmgmts:\\" & strComputer & "\root\cimv2"

Set objWMIService = GetObject(wmiRoot)

Set objProcessor = objWMIService.Get(cpu)

If objProcessor.Architecture = 0 Then

WScript.Echo "This is an x86 cpu."

ElseIf objProcessor.Architecture = 1 Then

WScript.Echo "This is a MIPS cpu."

ElseIf objProcessor.Architecture = 2 Then

WScript.Echo "This is an Alpha cpu."

ElseIf objProcessor.Architecture = 3 Then

WScript.Echo "This is a PowerPC cpu."

ElseIf objProcessor.Architecture = 6 Then

WScript.Echo "This is an ia64 cpu."

Else

WScript.Echo "Cannot determine cpu type."

End If

Header Information

The Header information section contains the usual information (discussed in Chapters 1 and

2), as shown here:

Option Explicit

On Error Resume Next

Dim strComputer

Dim cpu

Dim wmiRoot

Dim objWMIService

Dim objProcessor

Option Explicit tells VBScript that you’ll name all the variables used in the script by using the

Dim command. On Error Resume Next turns on basic error handling. The strComputer variable holds the name of the computer from which we will perform the Windows Management

Instrumentation (WMI) query. The cpu variable tells VBScript where in WMI we will go to read the information.

The wmiRoot variable enables you to perform a task you haven’t performed before in previous scripts: split out the connection portion of WMI to make it easier to change and more read­

Chapter 3 Adding Intelligence

65

able. The variables objWMIService and objProcessor hold information that comes back from the

Reference information section.

Reference Information

The Reference information section is the place where you assign values to the variables you named earlier in the script. The CPUType.vbs script contains these assignments: strComputer = "." cpu = "win32_Processor.deviceID='CPU0'" wmiRoot = "winmgmts:\\" & strComputer & "\root\cimv2"

strComputer is equal to ".", which is a shorthand notation for the local computer that the script is currently executing on. With the cpu variable, you define the place in WMI that contains infor­ mation about processors, which is win32_Processor. Because there can be more than one proces­ sor on a machine, you further limit your query to CPU0. It is necessary to use CPU0 instead of

CPU1 because win32_Processor begins counting CPUs with 0, and although a computer always has a CPU0, it does not always have a CPU1. DeviceID is the key value for the WIN32_Processor

WMI class. To connect to an individual instance of a processor, it is necessary to use the key value. The key of a WMI class can be discovered using wmisdk_book.chm from

\My Documents\Microsoft Press\VBScriptSBS\resources, or by using the wbemTest.exe utility from a CMD prompt. In this script, you’re only trying to determine the type of CPU running on the machine, so it isn’t necessary to identify all CPUs on the machine.

Worker and Output Information

The first part of the script declared the variables to be used in the script, and the second part of the script assigned values to some of the variables. In the next section, you use those vari­ ables in an If…Then…ElseIf construction to make a decision about the type of CPU installed on the computer.

The Worker and Output information section of the CPUType.vbs script is listed here:

Set objWMIService = GetObject(wmiRoot)

Set objProcessor = objWMIService.Get(cpu)

If objProcessor.Architecture = 0 Then

WScript.Echo "This is an x86 cpu."

ElseIf objProcessor.Architecture = 1 Then

WScript.Echo "This is a MIPS cpu."

ElseIf objProcessor.Architecture = 2 Then

WScript.Echo "This is an Alpha cpu."

ElseIf objProcessor.Architecture = 3 Then

WScript.Echo "This is a PowerPC cpu."

ElseIf objProcessor.Architecture = 6 Then

WScript.Echo "This is an ia64 cpu."

Else

WScript.Echo "Cannot determine cpu type."

End If

66

Part I Covering the Basics

To write a script like this, you need to know how win32_Processor hands back information so that you can determine what a 0, 1, 2, 3, or 6 means. By detailing that information in an

If…Then…ElseIf construct, you can translate the data into useful information.

The first two lines listed in the preceding script work just like a normal If…Then statement.

The line begins with If and ends with Then. In the middle of the If…Then language is the state­ ment you want to evaluate. If objProcessor returns a zero when asked about the architecture, you know the CPU is an x86, and you use WScript.Echo to print out that data.

If, on the other hand, objProcessor returns a one, you know that the CPU type is a millions of instructions per second (MIPS). By adding into the ElseIf statements the results of your research into return codes for WMI CPU types, you enable the script to handle the work of finding out what kind of CPU your servers are running. After you’ve used all the ElseIf state­ ments required to parse all the possible return codes, you add one more line to cover the potential of an unexplained code, and you use Else for that purpose.

Combine msgBox and CPU information

1. Open Notepad or the script editor of your choice.

2. Open the msgBox.vbs script and save it as YourNamePromptCPU.vbs.

3. At the very bottom of the newly renamed msgBox.vbs script, type Sub subCPU, as seen

below:

Sub subCPU

4. Open the CPUType.vbs script and copy the entire script to the clipboard.

5. Paste the entire CPUType.vbs script under the words Sub subCPU.

6. The first and second lines (from the CPUType.vbs script) that are pasted below the

words Sub subCPU are not required in our subroutine. The two lines can be deleted.

They are listed below:

Option Explicit

On Error Resume Next

7. Go to the bottom of the script you pasted under the words Sub subCPU and type End

sub. We have now moved the CPU-type script into a subroutine. We will only enter this

subroutine if the user presses the Yes button.

8. Under the code that evaluates the vbYes intrinsic constant, we want to add the line to call

the subroutine. To do this, we simply type the name of the subroutine. That name is

subCPU. The code to launch the script is seen below. Notice the only new code here is the word subCPU, everything else was already in the msgBox script.

If intRTN = vbYes Then

WScript.Echo "yes was pressed" subCPU

Chapter 3 Adding Intelligence

67

9. For every other button selection, we want to end the script. The command to do that is

WScript.quit. We will need to type this command in three different places, as seen below:

ElseIf intRTN = vbNo Then

WScript.Echo "no was pressed"

WScript.quit

ElseIf intRTN = vbCancel Then

WScript.Echo "cancel was pressed"

WScript.quit

Else

WScript.Echo intRTN & " was pressed"

WScript.quit

End If

10. Save and run the script. Press the Yes button, and the results from CPUType should be

displayed. Run the script two more times: Press No, and then press Cancel. On each suc­ cessive running, the script should exit instead of running the script. If these are not your results, compare the script with the PromptCPU.vbs script in the folder \My Docu­ ments\Microsoft Press\VBScriptSBS\ch03.

Quick Check

Q. How many ElseIf lines can be used in a script?

A. As many ElseIf lines as are needed.

Q. If more than one or two ElseIf lines are necessary, is there another construct that would be easier to use?

A. Yes. Use a Select Case type of structure.

Q. What is the effect of using strComputer = "." in a script?

A. The code strComputer is shorthand that means the local computer the script is executing on. It is used with WMI.

If…Then…Else

It is important to point out here that you can use If…Then…Else without the intervening ElseIf commands. In such a construction, you give the script the ability to make a choice between two options.

Just the Steps

To use If…Then…Else

1. On a new line in the script, type If some condition Then.

2. On the next line, enter the command you want to invoke.

3. On the next line, type Else.

68

Part I Covering the Basics

4. On the next line, type the alternate command you want to execute when the condition is not true.

5. On the next line, type End If.

The use of If…Then…Else is illustrated in the following code:

ifThenElse.vbs

Option Explicit

On Error Resume Next

Dim a,b,c,d a = 1 b = 2 c = 3 d = 4

If a + b = d Then

WScript.Echo (a & " + " & b & " is equal to " & d)

Else

WScript.Echo (a & " + " & b & " is equal to " & c)

End If

In the preceding ifThenElse.vbs script, you declare your four variables on one line. You can do this for simple scripts such as this one. It can also be done for routine variables that are asso­ ciated with one another, such as objWMIService and objProcessor from your earlier script. The advantage of putting multiple declarations on the same line is that it makes the script shorter.

Although this does not really have an impact on performance, it can at times make the script easier to read. You’ll need to make that call—does making the script shorter make the script easier to read, or does having each variable on a separate line with individual comments make the script easier to read?

When you do the WScript.Echo command, you’re using a feature called concatenation, which puts together an output line by using a combination of variables and string text. Notice that everything is placed inside the parentheses and that the variables do not go inside quotation marks. To concatenate the text into one line, you can use the ampersand character (&).

Because concatenation does not automatically include spaces, you have to put in the appropri­ ate spaces inside the quotation marks. By doing this, you can include a lot of information in the output. This is one area that requires special attention when you’re modifying existing scripts. You might need to change only one or two variables in the script, but modifying the accompanying text strings often requires the most work.

Using If…Then…Else to fix the syntax of output

1. Open the QueryAllProcessors.vbs script in the folder \My Documents\Microsoft

Press\VBScriptSBS\ch03 using Notepad or the script editor of your choice. Save it as

YourNameQueryAllProcessorsSyntax.vbs.

Chapter 3 Adding Intelligence

69

2. Put a new function definition at the end of the script. (We will discuss user defined func­

tions in just a few pages.) Use the word Function and give it the name funIS. Assign the input parameter the name intIN. The syntax for this line will look like the following:

Function funIS(intIN)

3. Space down a few lines and end the function with the words End Function. This com­

mand will look like the following:

End Function

4. Use If…Then to see if the intIN parameter is less than two. This line will look like:

If intIN <2 Then

5. If the intIN parameter is less than two, then we want to assign the string “is a” the

numeric value of intIN and the word Processor. The result will be that the script will use the singular form of the verb to be. This is seen in the line below: funIS = " is a " & intIN & " Processor "

6. If this is not the case, we will assign the string “are” and the number of processors to the

name of the function. Finally we close out the If…Then construction by using End If. This is seen below:

Else funIS = " are " & intIN & " Processors "

End If

7. Right after we assign the colItems variable to contain the object that comes back from

using the execQuery method, we want to retrieve the count of the number of items in

colItems. We also want to build an output string that prints out a string stating how many processors are on the machine. We will use the funIS function to build up the remainder of the output line. It will look like the following:

WScript.Echo "There" & funIS(colItems.count) & _

"on this computer"

8. Save and run the script. You may want to compare your results with the QueryAllProces­

sorsSyntax.vbs script in the folder \My Documents\Microsoft

Press\VBScriptSBS\ch03.

Select Case

When I see a Select Case statement in a script written in the VBScript language, my respect for the script writer goes up at least one notch. Most beginning script writers can figure out the

If…Then statement, and some even get the If…Then…Else construction down. However, few master the Select Case construction. This is really a shame, because Select Case is both elegant

70

Part I Covering the Basics

and powerful. Luckily for you, I love Select Case and you will be masters of this construction by the end of this chapter!

Just the Steps

To use Select Case

1. On a new line in the script, type Select Case and a variable to evaluate.

2. On the second line, type Case 0.

3. On the third line, assign a value to a variable.

4. On the next line, type Case 1.

5. On a new line, assign a value to a variable.

6. On the next line, type End Select.

In the following script, you again use WMI to obtain information about your computer. This script is used to tell us the role that the computer plays on a network (that is, whether it’s a domain controller, a member server, or a member workstation). You need to use Select Case to parse the results that come back from WMI, because the answer is returned in the form of 0,

1, 2, 3, 4, or 5. Six options would be too messy for an If…Then…ElseIf construction. The text of

ComputerRoles.vbs is listed here:

ComputerRoles.vbs

Option Explicit

'On Error Resume Next

Dim strComputer

Dim wmiRoot

Dim wmiQuery

Dim objWMIService

Dim colItems

Dim objItem strComputer = "." wmiRoot = "winmgmts:\\" & strComputer & "\root\cimv2" wmiQuery = "Select DomainRole from Win32_ComputerSystem"

Set objWMIService = GetObject(wmiRoot)

Set colItems = objWMIService.ExecQuery _

(wmiQuery)

For Each objItem in colItems

WScript.Echo funComputerRole(objItem.DomainRole)

Next

Function funComputerRole(intIN)

Select Case intIN

Case 0 funComputerRole = "Standalone Workstation"

Case 1 funComputerRole = "Member Workstation"

Case 2 funComputerRole = "Standalone Server"

Chapter 3 Adding Intelligence

71

Case 3 funComputerRole = "Member Server"

Case 4 funComputerRole = "Backup Domain Controller"

Case 5 funComputerRole = "Primary Domain Controller"

Case Else funComputerRole = "Look this one up in SDK"

End Select

End Function

Header Information

The Header information section of ComputerRoles.vbs is listed in the next bit of code. Notice that you start with the Option Explicit and On Error Resume Next statements, which are explained earlier in this chapter and in detail in Chapter 1, “Starting from Scratch.” Next, you declare six variables. wmiQuery is, however, a different variable. You’ll use it in the Reference information section, where you”ll assign a WMI query string to it. By declaring a variable and listing it separately, you can change the WMI query without having to rewrite the entire script.

objWMIService is used to hold your connection to WMI, and the variable colItems holds a col­ lection of items that comes back from the WMI query. objItem is used to obtain an individual item from the collection. This was discussed in Chapter 2. The complete Header information section is listed below:

Option Explicit

On Error Resume Next

Dim strComputer

Dim wmiRoot

Dim wmiQuery

Dim objWMIService

Dim colItems

Dim objItem

Reference Information

The Reference information section assigns values to many of the variables named in the

Header information part of ComputerRoles.vbs. The Reference information section of the script is listed here: strComputer = "." wmiRoot = "winmgmts:\\" & strComputer & "\root\cimv2" wmiQuery = "Select DomainRole from Win32_ComputerSystem"

Two variables are unique to this script, the first of which is wmiQuery. In the Collection-

OfDrives.vbs script discussed in Chapter 2, you embedded the WMI query in the GetObject command, which makes for a long line. By bringing the query out of the GetObject command and assigning it to the wmiQuery variable, you make the script easier to read and modify in the

72

Part I Covering the Basics

future. Next, you use the colItems variable and assign it to hold the object that is returned when you actually execute the WMI query.

Quick Check

Q. How is Select Case implemented?

A. Select Case begins with the Select Case command and a variable to be evaluated. How­ ever, it is often preceded by a For Each statement.

Q. How does Select Case work?

A. Select Case evaluates the test expression following the Select Case statement. If the result from this matches a value in any of the Case statements, it executes the code following that Case statement.

Q. What is the advantage of assigning a WMI query to a variable?

A. It provides the ability to easily use the script to query additional information from WMI.

Worker and Output Information

As mentioned earlier, WMI often returns information in the form of a collection (we talked about this in Chapter 2), and to work your way through a collection, you need to use the For

Each…Next command structure to pull out specific information. In the Worker information section of ComputerRoles.vbs, you begin with making a connection into WMI. We do this by using GetObject to obtain a hook into WMI. Once we have made the connection into WMI, we then execute a WMI query and assign the resulting collection of items to a variable called

colItems. We then use For Each…Next to pull one instance of an item from the collection so we can examine it. This is illustrated in code below. The interesting thing is the way we moved the

Select Case statement from the middle of the script into a function called funComputerRole.

Set objWMIService = GetObject(wmiRoot)

Set colItems = objWMIService.ExecQuery _

(wmiQuery)

For Each objItem in colItems

WScript.Echo funComputerRole(objItem.DomainRole)

Next

funComputerRole function

To simplify the reading of the script, and to make it easier to maintain the script, we move the

Select Case structure into a function we include at the bottom of the script. This moves the decision matrix out of the middle of the Worker section. It vastly simplifies the code (once, of course, you understand how a function works). In Figure 3-1, you can see that when we call the function, we use the name of the function. In parentheses, we include the parameter we wish to supply to the function. In the ComputerRoles.vbs script, we are retrieving a numeric value that corresponds to the role the computer plays in the network. If you look up the

Chapter 3 Adding Intelligence

WIN32_computerSystem class in the WMI Platform SDK (\My Documents\Microsoft

Press\VBScriptSBS\Resources\WMI_SDKBook.chm), you will see an article that lists all the valuable properties this class can supply. I have copied the values for domain role into

Table 3-1. Based on the chart that translates the values for computer role, I created the

funComputerRole function.

73

FunComputerRole(objItem.DomainRole)

Function funComputerRole(intIN)

SelectCase intIN

funComputerRole = “blablabla”

The “blablabla” string, newly assigned to the funComputerRole function NAME, is now passed back where it REPLACES the

FunComputerRole(objItem.DomainRole) stuff.

Inside Function funComputerRole is known as intIN.

If the case matches, then the string “blablabla” is assigned to the NAME of the function.

End FUNCTION

Figure 3-1 Assign value to name of the function

In Figure 3-1, you see how the numeric value of the computer role is passed to the funCompu­

terRole function. Once the number is inside the function, it is stored in the variable intIN. The

Select Case statement evaluates the value of intIN and assigns the appropriate string to the name of the function itself. As you can see in Figure 3-1, the value that is assigned to the name of the function is passed back to the line of code that called the function in the first place. The

funComputerRole function is listed below.

Function funComputerRole(intIN)

Select Case intIN

Case 0 funComputerRole = "Standalone Workstation"

Case 1 funComputerRole = "Member Workstation"

Case 2 funComputerRole = "Standalone Server"

Case 3 funComputerRole = "Member Server"

Case 4 funComputerRole = "Backup Domain Controller"

Case 5 funComputerRole = "Primary Domain Controller"

Case Else funComputerRole = "Look this one up in SDK"

End Select

End Function

To find out how the DomainRole field is structured, you need to reference the Platform SDK for Microsoft Windows Server 2003. You will also be able to find other properties you can use

74

Part I Covering the Basics

to expand upon the ComputerRoles.vbs script. The value descriptions for domain roles are shown in Table 3-1.

Table 3-1

WMI Domain Roles from Win32_ComputerSystem

3

4

5

Value

0

1

2

Meaning

Standalone workstation

Member workstation

Standalone server

Member server

Backup domain controller

Primary domain controller

The first line of the Select Case statement contains the test expression—the number represent­ ing the role of the computer on the network. Each successive Case statement is used to evalu­ ate the test expression, and to identify the correct computer role. The first of these statements is seen here:

Case 0 strComputerRole = "Standalone Workstation"

The strComputerRole variable will be assigned the phrase “Standalone Workstation” if the text expression (intIN) is equal to 0. You will then use strComputerRole to echo out the role of the computer in the domain when we exit the Select Case construction.

You end the Select Case construction with End Select, similarly to the way you ended the

If…Then statement with End If. After you use End Select, you use the WScript.Echo command to send the value of strComputerRole out to the user. Remember that the entire purpose of the

Select Case construction in ComputerRoles.vbs is to find and assign the DomainRole value to the strComputerRole variable. After this is accomplished, you use the Next command to feed back into the For Each loop used to begin the script.

Modifying CPUType.vbs Step-by-Step Exercises

In this section, you will modify CPUType.vbs so that it uses a Select Case format instead of multiple If…Then…ElseIf statements. This is a valuable skill, because many of the scripts you will find have a tendency to use multiple If…Then…ElseIf statements. As you will see, it is rela­ tively easy to make the modification to using Select Case. The key to success is to remove as lit­ tle of the original code as possible.

1. Open CPUTypeStarter.vbs and save it as YourNameCPUType.vbs. It is located in the

\My Documents\Microsoft Press\VBScriptSBS\Ch03\StepByStep folder.

2. Turn off On Error Resume Next by commenting out the line.

Chapter 3 Adding Intelligence

75

3. Turn the If…Then line into a Select Case statement. The only element you must keep from

this line is objProcessor.Architecture, because it is hard to type. When you are finished, your Select Case line looks like the following:

Select Case objProcessor.Architecture

4. Start your case evaluation. If objProcessor.Architecture = 0, you know that the processor is

an x86. So your first case is Case 0. That is all you put on the next line. It looks like this:

Case 0

5. Leave the WScript.Echo line alone.

6. ElseIf objProcessor.Architecture = 1 becomes Case 1, which is a MIPS CPU. Delete the entire

ElseIf line and enter Case 1.

7. Leave the WScript.Echo line alone.

ElseIf objProcessor.Architecture = 2 becomes simply Case 2, as you can see here:

Case 2

Up to this point, your Select Case configuration looks like the following:

Select Case objProcessor.Architecture

Case 0

WScript.Echo "This is an x86 cpu."

Case 1

WScript.Echo "This is a MIPS cpu."

Case 2

WScript.Echo "This is an Alpha cpu."

8. Modify the "ElseIf objProcessor.Architecture = 3 Then" line so that it becomes Case 3.

9. Leave the WScript.Echo line alone.

The next case is not Case 4, but rather Case 6, because you modify the following line:

"ElseIf objProcessor.Architecture = 6 Then". The Select Case construction now looks like the following:

Select Case objProcessor.Architecture

Case 0

WScript.Echo "This is an x86 cpu."

Case 1

WScript.Echo "This is a MIPS cpu."

Case 2

WScript.Echo "This is an Alpha cpu."

Case 3

WScript.Echo "This is a PowerPC cpu."

Case 6

WScript.Echo "This is an ia64 cpu."

10. You have one more case to evaluate, and it will take the place of the Else command,

which encompasses everything else that has not yet been listed. You implement Case

Else by changing the Else to Case Else.

76

Part I Covering the Basics

11. Leave the line WScript.Echo "Cannot determine cpu type" alone.

12. Change End If to End Select. Now you’re finished with the conversion of If…ThenElseIf

to Select Case.

13. Save the file and run the script. If you need assistance, refer to the CPUTypeSolution.vbs

script in the same folder you found the starter script.

One Step Further: Modifying ComputerRoles.vbs

In this lab, you’ll modify ComputerRoles.vbs so that you can use it to turn on Dynamic Host

Configuration Protocol (DHCP) on various workstations. This is the first script we use that calls a WMI method.

Scenario

Your company’s network was set up by someone who really did not understand DHCP. In fact, the person who set up the network probably could not even spell DHCP, and as a result every workstation on the network is configured with a static IP address. This was bad enough when the network only had a hundred workstations, but the network has grown to more than three hundred workstations within the past couple of years. The Microsoft Excel spreadsheet that used to keep track of the mappings between computer names and IP addresses is woe­ fully out of date, which in the past month alone has resulted in nearly 30 calls to the help desk that were traced back to addressing conflicts. To make matters worse, some of the helpful administrative assistants have learned to change the last octet in Transmission Control Proto­ col/Internet Protocol (TCP/IP) properties, which basically negates any hope of ever regaining a managed network. Your task, if you should choose to accept it, is to create a script (or scripts) that will do the following:

■ Use WMI to determine the computer’s role on the network and to print out the name of the computer, the domain name (if it is a member of a domain), and the user that belongs to the computer

■ Use WMI to enable DHCP on all network adapters installed on the computer that use

TCP/IP

Your research has revealed that you can use Win32_ComputerSystem WMI class to obtain the information required in the first part of the assignment.

Warning

Keep in mind, this script will change network settings on the machine that this script runs on. Also, when run, it will need administrator rights to make the configuration changes. If you do not wish to change your TCP/IP settings, then do not run this script on your machine.

Chapter 3 Adding Intelligence

77

Part A

1. Open up the ComputerRoles.vbs file from \My Documents\Microsoft PressVB

ScriptSBS\Ch03\OneStepFurther and save it as YourNameComputerRoles

Solution.vbs.

2. Comment out On Error Resume Next so that you will receive some meaningful feedback

from the Windows Script Host (WSH) run time.

3. Dim new variables to hold the following items:

strcomputerName

strDomainName

strUserName

4. Modify wmiQuery so that it returns more than just DomainRole from

Win32_ComputerSystem. Hint: Change DomainRole to a wildcard such as *. The original wmiQuery line is seen below: wmiQuery = "Select DomainRole from Win32_ComputerSystem"

The new line looks like this:

"Select * from Win32_ComputerSystem"

5. Because colComputers is a collection, you can’t directly query it. You’ll need to use For

Each…Next to give yourself a single instance to work with. Therefore, the assignment of your new variables to actual items will take place inside the For Each…Next loop. Assign each of your new variables in the following manner:

strComputerName = objComputer.name

strDomainName = objComputer.Domain

strUserName = objComputer.UserName

6. After the completion of the Select Case statement (End Select) but before the Next com­

mand at the bottom of the file, use WScript.Echo to return the four items required by the first part of the lab scenario. Use concatenation (by using the ampersand) to put the four variables on a single line. Those four items are declared as follows:

Dim strComputerRole

Dim strcomputerName

Dim strDomainName

Dim strUserName

7. Save the file and run it.

78

Part I Covering the Basics

8. Modify the script so that each variable is returned on a separate line. Hint: Use the

intrinsic constant vbCrLf and the ampersand to concatenate the line. It will look some­ thing like this: strComputerRole & vbCrLf & strComputerName

9. Save and run the file.

10. Use WScript.Echo to add and run a complete message similar to the following:

WScript.Echo(“all done”)

11. Save and run your script. If it does not run properly, compare it with

\My Documents\Microsoft PressVBScriptSBS\ch03\StepByStep\ComputerRoles

Solution.vbs.

Part B

1. Open the YourNameComputerRolesSolution.vbs file and save it as YourNameEn­

ableDHCPSolution.vbs.

2. Comment out On Error Resume Next so that you will receive some meaningful feedback

from the WSH run time.

3. Dim new variables to hold the new items required for this script. Hint: You can rename

the following items:

Dim colComputers

Dim objComputer

Dim strComputerRole

4. The new variables are listed here:

colNetAdapters

objNetAdapter

DHCPEnabled

5. Modify the wmiQuery so that it looks like the following:

wmiQuery = "Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE"

6. Change the following Set statement:

Set colComputers = objWMIService.ExecQuery (wmiQuery)

Now, instead of using colComputers, the statement uses colNetAdapters. The line will look like the following:

Set colNetAdapters = objWMIService.ExecQuery (wmiQuery)

7. Delete the Select Case construction. It begins with the following line:

Select Case objComputer.DomainRole

And it ends with End Select.

Chapter 3 Adding Intelligence

79

8. You should now have the following:

For Each objComputer In colComputers

WScript.Echo strComputerRole

Next

9. Change the For Each line so that it reads as follows:

For Each objNetAdapter In colNetAdapters

10. Assign DHCPEnabled to objNetAdapter.EnableDHCP(). You can do it with the following:

DHCPEnabled = objNetAdapter.EnableDHCP()

11. Use If…Then…Else to decide whether the operation was successful. If DHCP is enabled,

DHCPEnabled will be 0, and you want to use WScript.Echo to echo out that the DHCP is enabled. The code looks like the following:

If DHCPEnabled = 0 Then

WScript.Echo "DHCP has been enabled."

12. If DHCPEnabled is not set to 0, the procedure does not work. So you have your Else con­

dition. It looks like the following:

Else

WScript.Echo "DHCP could not be enabled."

End If

13. Conclude the script by using the Next command to complete the If…Then…Next con­

struction. You don’t have to put in a closing echo command, because you’re getting feed­ back from the DHCPEnabled commands.

14. Save and run the script. Compare your script with the EnableDHCPSolution.vbs script

in the \My Documents\Microsoft Press\VBScriptSBS\ch03\OneStepFurther folder.

Chapter 3 Quick Reference

To

Evaluate a condition using If…Then

Evaluate one condition with two outcomes

End an If…Then…Else statement

Use an intrinsic constant in a script

Evaluate one condition with three outcomes

Evaluate one condition with four potential outcomes

Do This

Place the condition to be evaluated between the words If and Then

Use If…Then…Else

Use End If

Type it into the code (it does not need to be de­ clared, or otherwise defined)

Use If…Then…ElseIf, or use Select Case

Use Select Case

Chapter 15

Using Subroutines and Functions

Before You Begin

To work through the material presented in this chapter, you need to be familiar with the following concepts from earlier chapters:

■ Reading text files

■ Writing to text files

■ Creating files

■ Creating folders

■ Using the For…Next statement

■ Creating the Select Case statement

■ Connecting to Microsoft Active Directory directory service

■ Reading information from WMI

After completing this chapter, you will be able to:

■ Convert inline code into a subroutine

■ Call subroutines

■ Perform Active Directory user management

Working with Subroutines

In this section, you’ll learn about how network administrators use subroutines. For many readers, the use of subroutines will be somewhat new territory and might even seem unnec­ essary, particularly when you can cut and paste sections of working code. But before we get into the how-to, let’s go over the what.

A subroutine is a named section of code that gets run only when something in the script calls it by name. Nearly every script we’ve worked with thus far has been a group of commands, which have been processed from top to bottom in a consecutive fashion. Although this con­ secutive processing approach, which I call linear scripting, makes the code easy for the net­

329

330

Part III Advanced Windows Administration

work administrator to work with, it does not always make his work very efficient. In addition, when you need to perform a similar activity from different parts of the script, using the inline cut-and-paste scripting approach quickly becomes inefficient and hard to understand. This is where subroutines come into play. A subroutine is not executed when its body is defined in the code; instead, it is executed only when it is called by name. If you define a subroutine, and use it only one time, you might make your script easier to read or easier to maintain, but you will not make the script shorter. If, however, you have something you want to do over and over, the subroutine does make the script shorter. The following summarizes uses for a sub­ routine in Microsoft Visual Basic, Scripting Edition (VBScript):

■ Prevents needless duplication of code

■ Makes code portable and reusable

■ Makes code easier to troubleshoot and debug

■ Makes code easier to read and maintain

■ Makes code easier to modify

The following script (LinearScript.vbs) illustrates the problem with linear scripting. In this script are three variables: a, b, and c. Each of these is assigned a value, and you need to deter­ mine equality. The script uses a series of If Then…Else statements to perform the evaluative work.

As you can see, the code gets a little redundant by repeating the same statements several times.

LinearScript.vbs

Option Explicit

Dim a

Dim b

Dim c a=1 b=2 c=3

If a = b Then

WScript.Echo a & " and " & b & " are equal"

Else

WScript.Echo a & " and " & b & " are not equal"

End If

If b = c Then

WScript.Echo b & " and " & c & " are equal"

Else

WScript.Echo b & " and " & c & " are not equal"

End If

If a + b = c Then

WScript.Echo a+b & " and " & c & " are equal"

Else

WScript.Echo a+b & " and " & c & " are not equal"

End If

Chapter 15 Using Subroutines and Functions

331

OK, so the script might be a little redundant, although if you’re paid to write code by the line, this is a great script! Unfortunately, most network administrators are not paid by the line for the scripts they write. This being the case, clearly you need to come up with a better way to write code. (I am telegraphing the solution to you now…) That’s right! You will use a subrou­ tine to perform the evaluation. The modified script uses a subroutine to perform the evalua­ tion of the two numbers. This results in saving two lines of code for each evaluation performed. In this example, however, the power is not in saving a few lines of code—it’s in the fact that you use one section of code to perform the evaluation. Using one section makes the script easier to read and easier to write.

Note

Business rules is a concept that comes up frequently in programming books. The idea is that many programs have concepts that are not technical requirements but still must be adhered to. These are nontechnical rules. For instance, a business rule might say that when a payment is not received within 30 days after the invoice is mailed, a follow-up notice must be sent out, and a 1 percent surcharge is added to the invoice amount. Because businesses some­ times change these nontechnical requirements, such rules would be better incorporated into a separate section of the code (a subroutine, for example) as opposed to sprinkling them throughout the entire program. If the business later decides to charge an additional 1 percent surcharge after 60 days, this requirement can be easily accommodated in the code.

In the script you are currently examining, your business rules are contained in a single code section, so you can easily modify the code to incorporate new ways of comparing the three numbers (to determine, for example, that they are not equal instead of equal). If conditions are likely to change or additional information might be required, creating a subroutine makes sense.

Quick Check

Q. To promote code reuse within a script, where is one place you can position the code?

A. You can place the code within a subroutine.

Q. To make changing business rules easier to update, where is a good place to position the rules?

A. You can place business rules within a subroutine to make them easier to update.

Calling the Subroutine

In the next script you’ll examine, SubRoutineScript.vbs, the comparison of a, b, and c is done by using a subroutine called Compare. To use a subroutine, you simply place its name on a line by itself. Notice that you don’t need to declare the name of the subroutine because it isn’t a variable. So, the script works even though you specified Option Explicit and did not declare the name used for the subroutine. In fact, you cannot declare the name of your subroutine. If you do, you will get a “name redefined” error.

332

Part III Advanced Windows Administration

Creating the Subroutine

Once you decide to use a subroutine, the code for creating it is very light. Indeed, all that is required is the word Sub followed by the name you will assign to the subroutine. In the

SubRoutineScript.vbs script, the subroutine is assigned the name Compare by the following line: Sub Compare. That’s all there is to it. You then write the code that performs the compari­ son and end the subroutine with the command End Sub. After you do all that, you have your subroutine.

SubRoutineScript.vbs

Option Explicit

Dim a, b, c

Dim num1, num2 a=1 b=2 c=3 num1 = a num2 = b compare num1 = b num2 = c compare num2 = c compare

Sub Compare

If num1 = num2 Then

WScript.Echo (num1 & " and " & num2 & " are equal")

Else

WScript.Echo(num1 & " and " & num2 & " are not equal")

End If

End Sub

Just the Steps

To create a subroutine

1. Begin the line of code with the word Sub followed by name of the subroutine.

2. Write the code that the subroutine will perform.

3. End the subroutine by using the End Sub command on a line by itself.

Creating Users and Logging Results

As your scripts become more powerful, they have a tendency to become longer and longer.

The next script, CreateUsersLogAction.vbs, is nearly 80 lines long. The reason for this length is that you perform three distinct actions. First, you read a text file and parse the data into an

Chapter 15 Using Subroutines and Functions

333

array. Then you use this array to create new users and add the users into an existing group in

Active Directory. As you create users and add them to groups, you want to create a log file and write the names of the created users. All the code to perform these actions begins to add up and can make a long script hard to read and understand. The subroutine becomes rather use­ ful in such a situation. In fact, the subroutine used to create the log file is nearly 30 lines long itself because you need to check whether the folder exists or the log file exists. If the folder or file does not exist, you need to create it. If each is present, you need to open the file and append data to it. By placing this code into a subroutine, you are able to access it each time you loop through the input data you’re using to create the users in the first place. After the user is created, you go to the subroutine, open the file, write to it, close the file, and then go back into Do Until…Loop to create the next user.

Note

Holding the text file open might seem like an easier approach than closing the file, but

I prefer to close the file after each loop so that I can guarantee the consistency of the file as a log of the accounts that are being created. Closing the file offers other benefits as well. It makes the operation more modular and therefore promotes portability. Making an open and a close part of the routine hides complexity that could arise.

If you kept the file open and wrote to the log file in an asynchronous manner, your log writer could get behind, and in the event of an anomaly, your log might not be an accurate reflection of the actual accounts created on the server. Here is the CreateUsersLogAction.vbs script.

CreateUsersLogAction.vbs

Option Explicit

On Error Resume Next

Dim objOU

Dim objUser

Dim objGroup

Dim objFSO

Dim objFile

Dim objFolder

Dim objTextFile

Dim TxtIn

Dim strNextLine

Dim i

Dim TxtFile

Dim LogFolder

Dim LogFile

TxtFile = "C:\UsersAndGroups.txt"

LogFolder = "C:\FSO"

LogFile = "C:\FSO\fso.txt"

Const ForReading = 1

Const ForWriting = 2

Const ForAppending = 8

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objTextFile = objFSO.OpenTextFile _

(TxtFile, ForReading)

334

Part III Advanced Windows Administration

Do Until objTextFile.AtEndOfStream strNextLine = objTextFile.ReadLine

TxtIn = Split(strNextLine , ",")

Set objOU = GetObject("LDAP://OU=mred," _

& "dc=nwtraders,dc=msft")

Set objUser = objOU.Create("User", "cn="& TxtIn(0)) objUser.Put "sAMAccountName", TxtIn(0) objUser.SetInfo

Set objGroup = GetObject _

("LDAP://CN="& TxtIn(1) & ",cn=users," _

& “dc=nwtraders,dc=msft”) objGroup.add _

"LDAP://cn="& TxtIn(0) & ",ou=Mred," _

& "dc=nwtraders,dc=msft"

Logging

Loop

Sub Logging

If objFSO.FolderExists(LogFolder) Then

If objFSO.FileExists(LogFile) Then

Set objFile = objFSO.OpenTextFile _

(LogFile, ForAppending) objFile.WriteBlankLines(1) objFile.Writeline "Creating User " & Now objFile.Writeline TxtIn(0) objFile.Close

Else

Set objFile = objFSO.CreateTextFile(LogFile) objFile.Close

Set objFile = objFSO.OpenTextFile _

(LogFile, ForWriting) objFile.WriteLine "Creating User " & Now objFile.WriteLine TxtIn(0) objFile.Close

End If

Else

Set objFolder = objFSO.CreateFolder(LogFolder)

Set objFile = objFSO.CreateTextFile(LogFile) objFile.Close

Set objFile = objFSO.OpenTextFile _

(LogFile, ForWriting) objfile.WriteLine "Creating User " & Now objFile.WriteLine TxtIn(0) objFile.Close

End If

End Sub

WScript.Echo("all done")

Chapter 15 Using Subroutines and Functions

335

Header Information

The Header information section of CreateUsersLogAction.vbs is used to declare all the vari­ ables used in the script. Thirteen variables are used in the script. The variable i is a simple counter and is not listed in Table 15-1 with the other variables.

Table 15-1

Variables Used in CreateUsersLogAction.vbs

Variable

objOU objUser objGroup objFSO objFile objFolder objTextFile

TxtIn strNextLine

TxtFile

LogFolder

LogFile

Description

Holds connection to target OU in Active Directory.

Holds hook for Create user command; takes TxtIn(0) as input for user name.

Holds hook for the add command; takes TxtIn(1) as input for name of group and

TxtIn(0) as name of user to add.

Holds hook that comes back from the CreateObject command used to create the

FileSystemObject.

Holds hook that comes back from the OpenTextFile command issued to objFSO.

Holds hook that comes back from the CreateFolder command issued to objFSO if the folder does not exist.

Holds the data stream that comes from the OpenTextFile command that is used to open the UsersAndGroups.txt file.

An array that is created from parsing strNextLine. Each field split by the comma becomes an element in the array. Holds user name to be created and the group that the user is to be added to.

Holds one line worth of data from the UsersAndGroups.txt file.

Holds path and name of text file to be parsed as input data.

Holds path and name of folder used to hold logging information.

Holds path and name of text file to be used as the log file.

Reference Information

The Reference information section of the script is used to assign values to some of the vari­ ables in the script. In addition to the mundane items such as defining the path and title for the text file used to hold the users and groups, in this section, you create three constants that are used in working with text files.

Note

If you create standard variable names, and you consistently use them in your scripts, you will make it easier to reuse your subroutines without any modification. For instance, if you use objFSO consistently for creating FileSystemObject, you minimize the work required to

“rewire” your subroutine. Of course, using the Find and Replace feature of Microsoft Notepad, or any other script editor, makes it rather easy to rename variables.

These constants are ForReading, ForWriting, and ForAppending. The use of these constants was discussed in detail in Chapter 4, “Working with Arrays.” The last two tasks done in the Refer­ ence information section of the script are creating an instance of the FileSystemObject and

336

Part III Advanced Windows Administration

using the OpenTextFile command so that you can read it in the list of users that need to be cre­ ated and the group to which each user will be assigned. Here is the Reference information sec­ tion of the script:

TxtFile = "C:\UsersAndGroups.txt"

LogFolder = "C:\FSO"

LogFile = "C:\FSO\fso.txt"

Const ForReading = 1

Const ForWriting = 2

Const ForAppending = 8

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objTextFile = objFSO.OpenTextFile _

(TxtFile, ForReading)

Worker Information

The Worker information section of the script is where the users are actually created and assigned to a group. To work through the UsersAndGroups.txt file, you need to make a con­ nection to the file. This was done in a previous Reference information section of the script, in which we assigned objTextFile to be equal to the hook that came back once the connection into the file was made. Think back to the pipe analogy (in Chapter 5, “More Arrays”), in which you set up a pump and pulled the text, one line at a time, into a variable called strNextLine. As long as data is in the text file, you can continue to pump the information by using the Read-

Line command. However, if you reach the end of the text stream, you exit the Do Until…Loop statement you created.

Do Until objTextFile.AtEndOfStream strNextLine = objTextFile.ReadLine

TxtIn = Split(strNextLine , ",")

Set objOU = GeCreateUsersLogAction.vbstObject("LDAP://OU=Mred," _

& "dc=nwtraders,dc=msft")

Set objUser = objOU.Create("User", "cn="& TxtIn(0)) objUser.Put "sAMAccountName", TxtIn(0) objUser.SetInfo

Set objGroup = GetObject _

("LDAP://CN="& TxtIn(1) & ",cn=users," _

& "dc=nwtraders,dc=msft") objGroup.add _

"LDAP://cn="& TxtIn(0) & ",ou=Mred," _

& "dc=nwtraders,dc=msft"

Logging

Loop

Output Information

Once you create a new user and assign that user to a group, you need to log the script changes.

To do this, you call a subroutine (in our script, called Logging) that opens a log file and writes the name of the new user that was created as well as the time in which the creation occurred.

The first task the Logging subroutine does is check for the existence of the logging folder that

Chapter 15 Using Subroutines and Functions

337

is defined by the variable LogFolder. To check for the presence of the folder, you use the Folder-

Exists method. If the folder is present on the system, you next check for the existence of the logging file defined by the LogFile variable. To check for the presence of the logging file, you use the FileExists method. If both of these conditions are copasetic, you open the log file by using the OpenTextFile command and specify that you will append to the file instead of over­ writing it (which is normally what you want a log file to do). In writing to the file, you use two different methods: WriteBlankLines to make the log a little easier to read, and WriteLine to write the user name and the time that user was created in the log.

If, on the other hand, the log folder exists but the log file does not exist, you need to create the log file prior to writing to it. This is the subject of the first Else command present in the sub­ routine. You use the CreateTextFile command and the LogFile variable to create the log file.

After the file is created, you must close the connection to the file; if you do not, you get an error message stating that the file is in use. After you close the connection to the log file, you reopen it by using the OpenTextFile command, and then you write your information to the file.

The other scenario our subroutine must deal with is if neither the folder nor the log file is in existence, in which case you have to create the folder (by using the CreateFolder method) and then create the file (by using the CreateTextFile method). It is necessary to use objFile.Close to close the connection to the newly created text file so that you can write your logging informa­ tion to the file. Once you write to the log file, you exit the subroutine by using the End Sub command, and you enter Do Until…Loop again. The Logging subroutine is shown here:

Sub Logging

If objFSO.FolderExists(LogFolder) Then

If objFSO.FileExists(LogFile) Then

Set objFile = objFSO.OpenTextFile _

(LogFile, ForAppending) objFile.WriteBlankLines(1) objFile.WriteLine "Creating User " & Now objFile.WriteLine TxtIn(0) objFile.Close

Else

Set objFile = objFSO.CreateTextFile(LogFile) objFile.Close

Set objFile = objFSO.OpenTextFile _

(LogFile, ForWriting) objfile.WriteLine "Creating User " & Now objFile.WriteLine TxtIn(0) objFile.Close

End If

Else

Set objFolder = objFSO.CreateFolder(LogFolder)

Set objFile = objFSO.CreateTextFile(LogFile) objFile.Close

Set objFile = objFSO.OpenTextFile _

(LogFile, ForWriting) objfile.WriteLine "Creating User " & Now objFile.WriteLine TxtIn(0)

338

Part III Advanced Windows Administration

objFile.Close

End If

End Sub

WScript.Echo("all done")

Using a subroutine to retrieve service information from WMI

1. Open the \My Documents\Microsoft Press\VBScriptSBS\Templates\wmiTemplate.vbs

script in Notepad or your favorite script editor and save it as YourNameListServicesIn-

Processes.vbs.

2. Comment out On Error Resume Next.

3. Edit the wmiQuery line so that you are selecting only processID and the name from

win32_Process. You want to, however, exclude the process ID that equals 0. This query will look like the following: wmiQuery = "Select processID, name from win32_Process where processID <> 0"

4. In the Header section of the script, declare a new variable to hold the process ID. Call

this variable intPID.

5. Inside the For Each…Next loop, delete all the WScript.Echo ": " & objItem lines except for

one. The completed For Each…Next loop will look like the following:

For Each objItem in colItems

WScript.Echo ": " & objItem.

Next

6. Modify the WScript.Echo line so that it prints out the name and the processed properties

from the win32_Process class. Include labels with each property to identity each of the properties as belonging to a process. My code to do this looks like the following:

WScript.Echo "Process Name: " & objItem.Name & " ProcessID: " & objItem.ProcessID

7. Store the value of the process ID in the variable intPID. This is seen below:

intPID = objItem.ProcessID

8. Save and run YourNameListServicesInProcesses.vbs. There should be no errors at this

point, and you should see an output similar to the following (of course your list of pro­ cesses will be different). The process names and the process IDs seen in the output from your script will compare to the ones seen in Taskmanager.exe (refer to Figure 15-1).

Process Name: System ProcessID: 4

Process Name: smss.exe ProcessID: 776

Process Name: csrss.exe ProcessID: 868

Process Name: winlogon.exe ProcessID: 892

Process Name: services.exe ProcessID: 940

Process Name: lsass.exe ProcessID: 952

Process Name: svchost.exe ProcessID: 1136

Chapter 15 Using Subroutines and Functions

Process Name: svchost.exe ProcessID: 1228

Process Name: svchost.exe ProcessID: 1352

Process Name: spoolsv.exe ProcessID: 1640

Process Name: explorer.exe ProcessID: 832

Process Name: wmiprvse.exe ProcessID: 632

Process Name: wmiprvse.exe ProcessID: 1436

Process Name: WINWORD.EXE ProcessID: 3764

Process Name: svchost.exe ProcessID: 2428

Process Name: PrimalScript.exe ProcessID: 2872

Process Name: cscript.exe ProcessID: 584

Process Name: wmiprvse.exe ProcessID: 3652

339

Figure 15-1 Taskmanager.exe view of processes and services; Svchost is comprised of several services.

9. Create a subroutine called SubGetServices. This is seen below:

' *** subs are below ***

Sub subGetServices

End Sub

10. Inside your new subroutine, declare three variables that will be used in the secondary

Windows Management Instrumentation (WMI) query. One variable will contain the query, one will contain the collection returned by the query, and one will hold the indi­ vidual service instances retrieved from the collection. The three variables you want to declare correspond to the variables used in the main body of the script: wmiQuery1,

colItems1, objItem1.

Dim wmiQuery1

Dim colItems1

Dim objItem1

340

Part III Advanced Windows Administration

11. Under the new variables you declared in the subroutine, assign a new query to

wmiQuery1 that selects the name from WIN32_Service, where processID is the same as the one stored in intPID. This query will look like the following: wmiQuery1 = "Select name from win32_Service where processID = " & intPID

12. On the line following wmiQuery1, use the colItems1 variable to hold the collection that is

returned by using the execQuery method to execute the query contained in wmiQuery1.

This code will look like the following:

Set colItems1 = objWMIService.ExecQuery(WmiQuery1)

13. Use For EachLoop to walk through colItems1. Use WScript.Echo to print out the name of

each service that corresponds to the query defined in wmiQuery1. This is seen below:

For Each objItem1 In colItems1

WScript.Echo vbTab, "Service Name: ", objItem1.Name

Next

14. In the main body of the script, after the line where the process ID is assigned to intPID,

call the subroutine you just created. The placement of the call to subGetServices is seen below: intPID = objItem.ProcessID subGetServices

15. Save and run your script. You should see a printout that now lists services running

inside processes. Compare your results with the listing below. If you do not see some­ thing like this (realizing the processes and services will be different), compare your script with \My Documents\Microsoft Press\VBScriptSBS\ch15\ListServicesIn

Processes.vbs.

Process Name: System ProcessID: 4

Process Name: smss.exe ProcessID: 776

Process Name: csrss.exe ProcessID: 868

Process Name: winlogon.exe ProcessID: 892

Process Name: services.exe ProcessID: 940

Service Name: Eventlog

Service Name: PlugPlay

Process Name: lsass.exe ProcessID: 952

Service Name: ProtectedStorage

Service Name: SamSs

Process Name: svchost.exe ProcessID: 1136

Service Name: DcomLaunch

Process Name: svchost.exe ProcessID: 1228

Service Name: RpcSs

Process Name: svchost.exe ProcessID: 1352

Service Name: AudioSrv

Service Name: CryptSvc

Service Name: EventSystem

Service Name: Nla

Service Name: RasMan

Chapter 15 Using Subroutines and Functions

Service Name: SENS

Service Name: ShellHWDetection

Service Name: TapiSrv

Service Name: winmgmt

Process Name: spoolsv.exe ProcessID: 1640

Service Name: Spooler

Process Name: explorer.exe ProcessID: 832

Process Name: wmiprvse.exe ProcessID: 632

Process Name: wmiprvse.exe ProcessID: 1436

Process Name: WINWORD.EXE ProcessID: 3764

Process Name: svchost.exe ProcessID: 2428

Service Name: stisvc

Process Name: wmplayer.exe ProcessID: 172

Process Name: Dancer.exe ProcessID: 1180

Process Name: PrimalScript.exe ProcessID: 1920

Process Name: wmiprvse.exe ProcessID: 3156

Process Name: cscript.exe ProcessID: 3468

341

Working with Functions

You have already used functions that are predefined in VBScript. These form the crux of most of the flexibility of VBScript. VBScript has more than 100 intrinsic functions, which provide the ability to perform string manipulation (mid, len, instr, instrrev), work with arrays (array,

ubound, lbound, split, join), and control the way numbers are handled (int, round, formatnum­

ber). With so much functionality, you might wonder why you need to create your own func­ tions. Although you can write much code that does not require functions, there may be times when functions will make it easier to reuse your code. In addition, functions often make it eas­ ier to read and understand what the script is doing. In the VideoAdapterRam_Hard

Coded.vbs script, video RAM is retrieved in bytes. To convert the number into something more manageable, we convert it into megabytes by dividing the number by 1,048,576. This causes a readability problem, as seen below.

VideoAdapterRAM_HardCoded.vbs

Option Explicit

'On Error Resume Next

Dim strComputer

Dim wmiNS

Dim wmiQuery

Dim objWMIService

Dim colItems

Dim objItem strComputer = "." wmiNS = "\root\cimv2" wmiQuery = "Select AdapterRAM from win32_videoController"

Set objWMIService = GetObject("winmgmts:\\" & strComputer & wmiNS)

Set colItems = objWMIService.ExecQuery(wmiQuery)

For Each objItem in colItems

WScript.Echo "AdapterRAM: " & objItem.AdapterRAM/1048576

Next

342

Part III Advanced Windows Administration

Add a function to convert to megabytes

1. Open the \My Documents\Microsoft Press\VBScriptSBS\ch15\VideoAdapter

Ram_HardCoded.vbs script in Notepad or the script editor of your choice and save it as

YourNameVideoAdapterRam_UseFunction.vbs.

2. At the bottom of the script, begin the function by using the command function call and

name the function convertToMeg. Define a single input to the function as intIn. Close out the function by using the End Function command. This is seen below:

Function convertToMeg(intIN)

End Function

3. Between the Function and the End Function statements, divide intIN by 1,048,576 and

assign the results to convertToMeg, as seen below: convertToMeg = intIN/1048576

4. In the WScript.Echo line in the main script, call the convertToMeg function and supply

objItem.AdapterRAM as the input parameter to the function. The modified output line is seen below:

WScript.Echo "AdapterRAM: " & convertToMeg(objItem.AdapterRAM)

5. Save and run the script. You should see the amount of video RAM reported in mega­

bytes. If not, compare your script with \My Documents\Microsoft Press\VBScriptSBS

\ch15\ VideoAdapterRam_UseFunction.vbs.

Comparing intrinsic function and user defined function

1. Open the \My Documents\Microsoft Press\VBScriptSBS\Templates\Blank

Template.vbs script in Notepad or the script editor of your choice and save the script as

YourNameFunString.vbs.

2. Add Option Explicit to the first noncommented line.

3. Use WScript.Echo to print out a line that calls the VBScript String intrinsic function. Tell

the String function to repeat a dash character 15 times. This is seen below:

WScript.Echo "Intrinsic string function",VbCrLf,string(15,"-")

4. At the bottom of the script, create a function called funString. Have the function accept

two input parameters called intIN and strChar. Close out the function by using End Func­

tion. This is seen below:

Function funString(intIN,strChar)

End Function

5. Inside the funString function, declare a variable to be used as a counter. Call this

variable j.

Chapter 15 Using Subroutines and Functions

343

6. Use a For EachNext loop to build up the string of repeated characters. Use j to count

from one to intIN.

For j = 1 To intIN

Next

7. Between For j = 1 to intIN and Next, add funString to itself and to strChar, as seen below:

funString = funString & strChar

8. Copy the previous WScript.Echo line and replace the String function with the funString

function, as seen below:

WScript.Echo "User string function",VbCrLf,funString(15,"-")

9. Save and run your script. The results from the two functions should be exactly the same.

If they are not, compare your script with \My Documents\Microsoft Press\VBScriptSBS

\ch15\FunString.vbs.

Using ADSI and Subs, and Creating Users

Step-by-Step Exercises

In this section, you will expand the script used in this chapter. Instead of creating only a user, you will add information to the user. You will use a subroutine to perform logging.

1. Open Notepad or your favorite script editor.

2. Open the \My Documents\Microsoft Press\VBScriptSBS\ch15\StepByStep\Cre­

ateUsers.vbs file and save it as YourNameCreateMultipleUsersSolution.vbs.

3. Make sure you have a file called C:\fso\UsersAndGroups.txt, and run the

CreateUsers.vbs file. Go into Active Directory Users And Computers (ADUC) and delete the users that were created.

4. Cut the code used to open the text file that holds the names of users to add to Active

Directory. It is under the variable declarations, in the Reference information section of the script. It is five lines long. This code looks like the following:

TxtFile = "C:\fso\UsersAndGroups.txt"

Const ForReading = 1

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objTextFile = objFSO.OpenTextFile _

(TxtFile, ForReading)

5. Paste the code after the WScript.Echo command at the end of the script.

344

Part III Advanced Windows Administration

6. Under the declarations, where the txtFile code used to be, type ReadUsers. This is the

name of the new subroutine you will create. It will look like the following:

Dim objOU

Dim objUser

Dim objGroup

Dim objFSO

Dim objTextFile

Dim TxtIn

Dim strNextLine

Dim i

Dim TxtFile dim boundary

ReadUsers

7. On the line before the code that reads TxtFile, which you copied to the end of your

script, use the Sub command to create a subroutine called ReadUsers.

8. At the end of the subroutine, add the End Sub command. The completed subroutine

looks like the following:

Sub ReadUsers

TxtFile = "c:\fso\UsersAndGroups.txt"

Const ForReading = 1

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objTextFile = objFSO.OpenTextFile _

(TxtFile, ForReading)

End Sub

9. Save your work. Run the script to make sure it still works. Open Active Directory Users

And Computers and delete the users that were created by running the script.

10. Modify the subroutine so that it is reading a text file called MoreUsersAndGroups.txt.

This file is located in the \My Documents\Microsoft Press\VBScriptSBS\ch15\Step

ByStep folder.

Note

If you do not add the full path to the MoreUsersAndGroups.txt file, you will need to ensure you are running the script from the same directory where the file is located.

11. In the Worker section of the script that creates the user, use the Put method to add the

user’s first name, last name, building, and phone number. The Active Directory attributes are called givenName, sn, physicalDeliveryOfficeName, and telephoneNumber.

Each of these fields is in the array that gets created, so you need to increment the array field. The completed code will look like the following:

Set objUser = objOU.Create("User", "cn="& TxtIn(0)) objUser.Put "sAMAccountName", TxtIn(0) objUser.Put "givenName", TxtIn(1) objUser.Put "sn", TxtIn(2)

Chapter 15 Using Subroutines and Functions

345

objUser.Put "physicalDeliveryOfficeName", TxtIn(3) objUser.Put "telephoneNumber", TxtIn(4)

12. Because the group membership field is the last field and you added fields to the text file,

you need to increment the array index that is used to point to the group field. The new index number is 5, and the code will look like the following:

Set objGroup = GetObject _

("LDAP://CN="& TxtIn(5) & ",cn=users,dc=nwtraders,dc=msft")

13. Save the script and run it. After you successfully run the script, delete the users created

in Active Directory.

One Step Further: Adding a Logging Subroutine

In this section, you add logging capability to the script you finished in the Step-by-Step exercise.

1. Open Notepad or some other script editor.

2. Open \My Documents\Microsoft Press\VBScriptSBS\ch15\OneStepFurther\Create

MultipleUsersStarter.vbs and save the file as YourNameCreateMultipleUsers

Logged.vbs.

3. After the objGroup.add command statement but before the Loop command, add a call

to the subroutine called LogAction. The modification to the script will look like the following:

Set objGroup = GetObject _

("LDAP://CN="& TxtIn(5) & ",cn=users,dc=nwtraders,dc=msft") objGroup.Add _

"LDAP://cn="& TxtIn(0) & ",ou=Mred,dc=nwtraders,dc=msft"

LogAction

Loop

4. Under the ReadUsers subroutine, add a subroutine called LogAction. This will consist of

the Sub command and the End Sub command. Leave two blank lines between the two commands. The code will look like the following:

Sub LogAction

End Sub

5. Save your work.

6. Open the \My Documents\Microsoft Press\VBScriptSBS\ch15\OneStepFurther\

CreateLogFile.vbs file and copy all the variable declarations. Paste them under the vari­ ables in your script.

7. Delete the extra objFSO variable.

346

Part III Advanced Windows Administration

8. Copy the three reference lines from the CreateLogFile.vbs script and paste them under

the variable declarations. This section of the script now looks like the following:

Dim objOU

Dim objUser

Dim objGroup

Dim objFSO

Dim objTextFile

Dim TxtIn

Dim strNextLine

Dim i

Dim TxtFile

Dim objFile

Dim message

Dim objData1

'holds hook to the file to be used

'holds message to be written to file

'holds data from source used to write to file

'holds data from source used to write to file Dim objData2

Dim LogFolder

Dim LogFile message="Reading computer info " & Now objData1 = objRecordSet.Fields("name") objData2 = objRecordSet.Fields("distinguishedName")

9. Modify the message so that it states that the code is creating a user, and use the element

TxtIn(0) as the user name that gets created. This modified line will look like the following: message="Creating user " & TxtIn(0) & Now

10. Move the message line to the line after you parse strNextLine. You do this because you

are using an element of the array that must be an assigned value before it can be used. strNextLine = objTextFile.ReadLine

TxtIn = Split(strNextLine , ",") message="Creating user " & TxtIn(1) & Now

11. Modify the objData1 and objData2 data assignments. Use TxtIn(0) for the user field and

TxtIn(5) for the group. The two lines will look like the following: objData1 = TxtIn(0) objData2 = TxtIn(5)

12. Copy the remainder of the script and paste it between the two lines used to create the

subroutine. The completed section looks like the following:

Sub LogAction

If objFSO.FolderExists(LogFolder) Then

If objFSO.FileExists(LogFile) Then

Set objFile = objFSO.OpenTextFile(LogFile, ForAppending) objFile.WriteBlankLines(1) objFile.Writeline message objFile.Writeline objData1 objFile.Writeline objData2 objFile.Close

Else

Set objFile = objFSO.CreateTextFile(LogFile) objFile.Close

Chapter 15 Using Subroutines and Functions

Set objFile = objFSO.OpenTextFile(LogFile, ForWriting) objfile.WriteLine message objFile.WriteLine objData1 objFile.WriteLine objData2 objFile.Close

End If

Else

Set objFolder = objFSO.CreateFolder(LogFolder)

Set objFile = objFSO.CreateTextFile(LogFile) objFile.Close

Set objFile = objFSO.OpenTextFile(LogFile, ForWriting) objfile.writeline message objFile.WriteLine objData1 objFile.WriteLine objData2 objFile.Close

End If

End Sub

13. Save and run the script.

Chapter 15 Quick Reference

347

To

Create a subroutine

Call a subroutine

Make code more portable and easier to read and troubleshoot, and to promote code reuse

Do This

Begin a line with the word Sub followed by the name of the subroutine. You end the subroutine by using the command End Sub on a line following your subroutine code.

Place the name of the subroutine on a line by itself at the place in your code where you want to use the subroutine.

Use a subroutine.

Index

A

Access database, ADO to query, 308–309

Active Directory changes to, 257 connect to, 252, 293–297 control script execution while querying, 312–314 create ADO query into, 311–312 fill out profile tab in, 279 limit search, 300 modify user properties in, 270 objects used to search, 297 organizational attributes in, 282 schema cache, 350 search, 294

Sysvol share in, 352 telephone tab attributes in, 280 in Windows Server 2003, 298

Active Directory Migration Tool (ADMT), 253

Active Directory Schema MMC, 303–304

Active Directory Service Interfaces (ADSI) binding, 256–257 create computer account, 261–262 create groups in, 260–261 create multiple users, 280–281 create users with, 258–262 creating multi-valued users, 265–267 delete users, 287–290

Edit snap-in, 254 event log, 290–291

Flag property, 298 general user information, 270–271

IADsContainer, 256

LDAP names, 255 merge WMI and, 322–323 modify organizational settings, 281–282 modify terminal server settings, 283–287 modifying address tab information, 274–282

Output information, 257–258, 273 provider, 253–254

Reference information, 253–254, 272 user profile settings, 278 user telephone settings, 279–280

Worker information, 255–256, 272–273 working with, 251–257 working with users, 269–273

See also Active Directory

Active Directory Users and Computers (ADUC), 270,

274

ActiveX Data Objects (ADO) create effective queries, 297–299

Global Catalog server, 303–311

Header information, 295

Output information, 296–297, 301–303

Reference information, 295, 301 search for specific types of objects, 299–303 search properties, 298–299 to query Access database, 308–309 to query Excel spreadsheet, 307–308 to query text file, 309–311

WMI-network connection, 316–317

Worker information, 296–297

Address tab mappings, 275 modify information on, 274–282

Output information, 277–282

Reference information, 275

Worker information, 275

ADO. See ActiveX Data Objects

ADouWMIDHCP.vbs, 322–323

ADsDSOObject provider, 296, 319

ADSI. See Active Directory Service Interfaces

Adsldp.dll file, 349

ADSystemInfo interface, 356

Ampersand (&), 5, 12, 68, 89

Angle brackets (<>), 295

appActivate method, 49

ArgComputerService.vbs, 87–88, 90

Arguments command-line, 81–83 multiple, 86–89 named, 85, 90–93 passing, 81, 103–107

"subscript out of range," 84 supply value for missing, 85–86 unnamed, 85–86

Array building, 107–111 command-line arguments, 81–83 create, 93 defined, 93 detecting properties, 210–211

Join function and, 357 moving past dull, 95–100 passing arguments, 81, 103–107 tell me your name, 89–93 two-dimensional, 101–103 using multiple arguments, 86–89 working with, 93–95

ArrayReadTxtFileUBound.vbs, 98

ArrayReadTxtFile.vbs, 95–98

ASCII, 49

atEndOfStream, 59

469

470

Attribute indexing

Attribute indexing, 304–305

Attributes, query multiple, 302–303

Automatic cleanup, 172–174

Automation objects, 10

B

Backup window, 176

BasicArrayForEachNext.vbs, 94–95

BasicArrayForNext.vbs, 94

BasicQuery.vbs, 294–295

BindFolder.vbs, 175

Binding, 256–257

Binding string, 256–257

BIOSVersion property, 209–210

Business rules, 331

C

Capitalization, WMI properties and, 231

Capture error, 360

Carriage return, 61

Case sensitive, ADSI provider names as, 253

Change method, 200

CheckArgsPingMultipleComputers.vbs, 84–85

CheckNamedArgCS.vbs, 93

CheckServiceStatus.vbs, 99–100

CIM_Component class, 396

CIM_ElementSetting class, 396

CIM_LogicalDevice class, 200

CIM_ManagedSystemElement class, 395

CIM_Setting class, 395–396

CIMSettingClass.vbs, 397–398

Cleanup, automatic, 172–174

CmdDir.vbs, 369

CollectionOfDrivers.vbs, 26–27

Collections, 29–30

Command-line arguments create user error message, 84–86 defined, 81–86 implement, 82 modify, 82–83 no arguments, 84 run from command prompt, 83

Command-line syntax, 90

Command object, 297

Command prompt, run command-line arguments from,

83

Comment, 13

Common classes, 194

Common name (cn), 259

Computer account, create, with ADSI, 261–262

ComputerRoles.vbs, 70–71, 76–79

comspec variable, 368–369

Concatenation, 5, 12, 68, 89

Connection object, 297–297

ConnectToADOU.vbs, 316–317

Constants benefits of, 28–29 defining, 27

vs. variables, 27–29

Consumers, WMI, 188

Continuation character, 89

CopyFolderExtended.vbs, 176–177

CopyFolder.vbs, 176

Core classes, 194

Count method, 94

Country codes, ISO 3166-1, 276

CPUTypeStarter.vbs, 74

CPUType.vbs script, 64–66, 74–79

CreateAddRemoveShortCut.vbs, 50

CreateBasicFolder_checkFirst.vbs, 175

CreateBasicFolder.vbs, 166

CreateMultiFolders.vbs, 166 automatic cleanup, 172–174

Header information, 167

Output information, 167–168

Reference information, 167

Worker information, 167–168

CreateObject command, 165–167, 172, 296–297, 319

CreateOU.vbs, 252–253, 255–256

CreateRegKey.vbs, 373–374

CreateShortCut method, 49–50

CreateSite.vbs, 399–401

CreateUser.vbs, 258–259

CreateUsersLogAction.vbs, 332–334

Creating a literal, 27

CScript, 6, 12, 21–22, 41

Cscript.exe, 13

.csv file, 236

D

Database corruption, WMI, 419

Dataset, 201

DCOM security, 432

Defaults, accepting WMI, 208–214

Definitive software library (DSL), 355

DeleteBasicFolder.vbs, 172

DeleteMultiFolders.vbs, 173–174

DeleteRegKey.vbs, 377

DeleteUser.vbs, 288–289

Dependencies, 421

DHCP, 76

Diagnostic information, obtain, 426–432

Dim command, 6–7, 17–19, 27–28, 93–94, 108 variables announced by, 32–33

DisplayAdminTool.vbs, 4

DisplayComputerNames.vbs, 5–6, 19, 59–61

DisplayComputerNameWithComments.vbs, 13–14

DisplayProcessInformation.vbs, 31–33

DisplayWPAStatus.vbs, 201–203

funfix function

Distinguished names, 255–256

Distributed Component Object Model (DCOM) security issues, 419

DNS domain name of currently logged-on user, 15

Do…Loop command, 47

DoLoopMonitorForProcessDeletion.vbs, 47

Do Until...Loop, 333

Do Until loop, 97–98, 110 defined, 43

Header information, 44

Reference information, 44 worker and output information, 45–46

Do Until…Next command, 97–98

Do While...Loop command, 37–43 difference between Do Until and, 46

Header information, 38–39

Output information, 40–43, 59, 61

Reference information, 39–40

Worker information, 40–43, 59, 61

Do While True, 41, 47

Domain components (DCs), 259

Domain name, 259

DSL. See Definitive software library

Dull arrays, 95–100

Dynamic classes, 194

Dynamic Host Configuration Protocol (DHCP), 320–

321

E

Echo command, 12, 49, 176

EnableDHCP.vbs, 320–321

Encrypt Password property, 298

End If command, 46, 56, 61, 93

End Select, 74

End Sub command, 191

Err tool, 429–430 output from, 434

Error handling process, 7

Error message, create useful, 84–86

Error object, 297

Errors, WMI, common sources of, 419–420

Event log, 290–291

Excel spreadsheet, ADO to query, 307–308

Exchange 2003, 407–418 connect to MicrosoftExchangeV2, 408–409

Exchange_FolderTree, 413–414

Exchange_Logon, 414–416

Exchange_Mailbox, 416–418

Exchange_QueueSMTPVirtual

Server, 409

Header information, 409–410

MicrosoftExchangeV2 namespace, 407

Output information, 410–411 public folders, 411–413

Worker information, 410

Exchange WMI namespace, changes to, 407–408

ExchangeFolderTree.vbs, 413–414

ExchangePublicFolders.vbs, 411–413

ExchangeSMTPQueue.vbs, 409–410

Exec method, 49–50

Exists method, 92

Exit Do, 41

ExpandEnvironmentStrings method, 49

F

Field object, 297

FileSystemObject class, 44, 165, 167, 172

CopyFolder method, 176 folders and, 174–175

MoveFolder method, 179

OpenTextFile method, 171

Filter command, 108

FilterComputers.vbs, 300

Filtered print monitor, 386–388

FilterPrinterStatus.vbs, 386–387

Firewall issues, 420

Folders, 165–172 binding to, 174–175 check on existence of, 175 copying, 176–179 create, 182–183 create basic, 165–166 create multiple, 166 create programmatically, 173 delete, 172–174, 184 listing sizes, 177–178 moving, 178–181

For Each...Next, 72, 94 defined, 26

Header information, 27–30

Reference information, 30 step-by-step exercises, 51–52

Worker information, 30–31

formatNumber function, 41–43, 62, 177

For...Next, 31–37, 94, 97–98, 102–103

CreateObject code with, 168

Header information, 32–33

Reference information, 33–34 worker and output information, 34–37

ForReading constant, 44, 57, 96, 110

ForWriting constant, 57

FSOTemplate.vbs, 177

funComputerRole function, 72–74

Functions add, to convert to megabytes, 342 compare intrinsic and user defined, 342–343 working with, 341–343

funfix function, 287

471

472

GetCommentsTimed.vbs

G

GetCommentsTimed.vbs, 60

GetComments.vbs, 56–57, 59

GetStringValue, 375

Global Catalog server, 303–311 query, 305–306

Group add to logon script, 360–362 create, with ADSI, 260–261

Group Policy Objects (GPOs), 352

Group Policy server, 15

H

Header information

ADO, 295 create users log, 335 create Web sites, 400–401

CreateMultiFolders.vbs, 167

Do Until...Loop, 44

Do While...Loop, 38–39

EnableDHCP, 321

Exchange 2003, 409–410

For Each...Next, 27–30

For...Next, 32–33

If Then, 57

If...Then...Elself, 64–65, 85

IIS 6.0 connection, 397–398 logon scripts, 354–355 modify, 15–16 monitor printer status, 383–384 move past dull arrays, 96 multiple arguments, 88 reasons for, 5–6 registry connection, 371 registry key, 374 script, 5–9, 16–18

Select Case, 71 two-dimensional arrays, 102

WMI query, 228–229

WMI script, 202

WMI-network connection, 317–318

Hierarchical namespace, 188–191

Hotfix information, retrieving, 204–205

I

IADsADSystemInfo interface, 349–351

IADsContainer, 256

If...Then, 41, 46, 55–62, 93, 106

Header information, 57

Reference information, 57–58

Worker and Output information, 58–62

If...Then...Else, 67–69

If...Then...Elself

Header information, 64–65

Reference information, 65 use, 62–63

Worker and output information, 65–67 ifThenElse.vbs, 68

If...Then End if, 61–62

IfThen.vbs script, 55–56

IIS 6.0

back up metabase, 403–404 connection, 397–399 create Web site, 399–402 import metabase, 404–406 locate WMI classes for, 395–397

IlsStructuredDataClass class, 396

Impersonation levels, 214–215

InformativeWMI.vbs, 245–247

Infrastructure, WMI, 188

Inputbox search, 197

InStr command, 45–46

InStr function, 60

Intelligence, adding, 55–79

Internet Protocol (IP) address, 51, 252

Intrinsic constants, 61

IP. See Internet Protocol (IP) address

ISO 3166, 276

J

Join function, 210, 357

JScript, 13

K

Key properties, 232–233

L

LBound, 97

LDAP names, 255

LDAP provider, 253–254, 316

Lightweight Directory Access Protocol (LDAP), 270

Linear scripting, 329

LinearScript.vbs, 330–331

Line concatenation, 5. See also Concatenation

Line continuation, 5, 89

Line feed, 61

ListClassMethods.vbs, 199–200

ListClassProperties.vbs, 198

ListName_Only_AllShares.vbs, 231

ListName_Path_Max_Shares.vbs, 232

ListShares.vbs, 228, 230–231

ListSpecificGreaterThanShares.vbs, 228–241

ListSpecificShares.vbs, 237–238

ListSpecificWhereVariableShares.vbs, 241–242

ListWMIClasses.vbs, 194–195

ListWMINamespaces.vbs, 189–191

ListWMIProviders.vbs, 192–193

Open command prompt, dragging and dropping .vbs file to

Local computer, IADsADSystemInfo interface and, 349

LogEvent method, 49, 291

Logging add to logon script, 362–364 service accounts, 239–241 use subroutine to perform, 343–345 verbose WMI, 427

WMI, 433–437

Logging subroutine, 234–237, 336–338, 345–347

Logon script add group to, 360–362 add logging to, 362–364 deploy, 352–358

Header information, 354–355

IADsADSystemInfo interface, 349–351

Output information, 358–360

Reference information, 355–356 use, 351

Worker information, 357–358

WshNetwork class, 356

LogonScript.vbs, 353–358

Loop counter, 103

Loop Until, 46

M

Machine boot configuration, WMI moniker to display,

221–222

Managed Object Format (MOF) format, 425

Metabase back up IIS 6.0, 403–404 import IIS 6.0, 404–406

Methods defined, 10–11

WMI, 199–200

Microsoft Excel, 21

.csv file opens, 236

Microsoft Exchange 2000 domain information, 15

Microsoft Management console (MMC), 254

Microsoft Windows Me, 15

Microsoft Windows 95, 15

Microsoft Windows 2000, 15

Microsoft Windows XP, 15

MicrosoftDNS namespace, 188

MicrosoftExchangeV2 namespace, 407

MicrosoftIISv2 namespace, 396–397

Millions of instructions per seconds (MIPS), 66

ModifyTerminalServerProperties.vbs, 284–285

ModifyUserAddressTab.vbs, 274–275

ModifyUserProperties.vbs, 270–273

MOF files, compiling, 437–439

MofComp.exe, 430–431, 437–439

Moniker, 190. See also WMI moniker

MonitorForChangedDiskSpace.vbs, 38, 47

MonitorPrinterStatus.vbs, 383–384

MonitorPrintQueue.vbs, 388–389

MoveFolder.vbs script, moving, 179

MrEd OU, 254

MsgBox, 12

msgBox function, 180 msgBox.vbs script, 63

Multiple users, create, 280–281

N

“Name redefined” error, 331

Named arguments, 85, 90–93

NamedArgCS.vbs, 91–92

Namespace default, 190 defined, 189–191

Exchange WMI, 407

WMI, 189–191

Naming convention, Lightweight Directory Access Proto­ col (LDAP), 270

NDS provider, 253

Networking components change TCP/IP settings, 320–321 merge WMI and ADSI, 322–323, 326–327

Win32_NetworkAdapterConfiguration, 323–325

WMI and, 315–320, 325–326

Next command, 35

Notepad add, to SendTo menu, 22

CScript, 21 drag and drop .vbs file to, 21 use, to speed script modification, 17

Now command, 35, 176–178

Null string, 46

numLoop, 103

NWCOMPAT provider, 253

nwtraders.msft, 254

O

473

Object create additional, 48–51 defined, 10–11 search for specific types of, with ADO, 299–303 select specific properties from, 236

WMI, 189–191

objectCategory attribute, 299

ObjTxtFile, 96–97

On Error Resume Next, 27–28 benefit of, 229 function of, 6–8

If Then, 56 with ListShares.vbs, 228 logon script and, 353, 354 turn off during development, 7, 32–33

Open command prompt, dragging and dropping .vbs file to, 21

474

OpenTextFile command

OpenTextFile command, 59

Operator

VBScript, 238–239

WMI query using, 238–241

Option Explicit

first line of script, 6–7, 27–28, 32–33, 38–39, 41, 44 as spelling checker, 38–39

Organizational settings, modify, 281–282

Organizational unit (OU) structure, 251, 263–265

Output information

ADO, 296–297, 301–303

ADSI, 257–258, 273

ADSI address tab script, 277–282 create ADSI users, 260–262 create users log, 336–341 create Web sites, 402

CreateMultiFolders.vbs, 168

Do Until...Loop, 45–46

Do While...Loop, 40–43, 61

EnableDHCP, 321

Exchange 2003, 410–411 filtered print monitor, 387, 389

For Each...Next, 102–103

For...Next, 34–37

If…Then, 58–62

If...Then...Else, 68–69

If...Then...Elself, 65–67

IIS 6.0 connection, 399 logon scripts, 358–360 modify, 19–22 monitor printer status, 385 move past dull arrays, 96–97 registry connection, 371–372 registry key, 374–375 script, 12–13, 19–22

Select Case, 72–74 two-dimensional arrays, 102–103 using multiple arguments, 88

WMI moniker, 209

WMI query, 229–230

WMI script, 203

overwriteFiles constant, 176

P

Parameter object, 297

Pascal-cased, Windows NT as, 253

Passing arguments, 81, 103–107

Password property, 298

Ping script, modify, 52–53

PingMultipleComputers.vbs, 83

Ping.vbs script, 82–83

Platform SDK, defined privileges in, 215–216

PopUp method, 49

Printers check status of print server, 391–392 create filtered print monitor, 386–388 monitor print queues, 388–391 obtain status of, 382–385

Win32_Printer, 381–382

Privilege strings, 216

Processes, Taskmanager.exe view of, 338

Properties defined, 10–11 detecting array, 210–211 list running, 233–234 select specific, from object, 236

Terminal Server setting, 282–283

Win32_Share, 229–230

WMI, 197–199

Property object, 297

Provider, security issues, 419

Put command, 273, 276

Put method, 260

Q

Query

Global Catalog server, 305–306 security event log, 216–219

WMI, 201–204

Quotation marks, WMI query in, 217

R

ReadHotFixes.vbs, 370–372

ReadTextFile.vbs, 43

RecordSet object, 297–297

Reference information, 39–40

ADO, 295, 301

ADSI, 253–254, 272

ADSI address tab script, 275 create ASDI users, 259 create users log, 335–336 create Web sites, 401–402

CreateMultiFolders.vbs, 167

Do Until...Loop, 44

EnableDHCP, 321 filtered print monitor, 387

For Each...Next, 30

For...Next, 33–34

If Then, 57–58

If...Then...Elself, 65

IIS 6.0 connection, 398–399 logon scripts, 354–356 modify, 16–18 monitor printer status, 384 move past dull arrays, 96 purpose of, 9 registry connection, 371–372

registry key, 374–375 script, 8–9, 16–18

Select Case, 71–72 two-dimensional arrays, 102 using multiple arguments, 88

WMI moniker, 208–209

WMI query, 229

WMI script, 202–203

WMI-network connection, 318

R

RegDelete method, 49

Registry back up of, 367–380 connect to, 370–372 create registry keys, 373–375 create WshShell Object, 368–369 creating keys, 378–379 delete information, 376–377 read using WMI, 377–378

StdRegProv class, 372–373 writing to, 375–376

Registry Editor, Copy Key Name feature, 9

Registry key, 7–9 12

RegRead method, 49

RegWrite method, 49

Relative distinguished names (RDNs), 255

Replace dialog box, 18–19

Resources, WMI, 188

Resultant Set of Policy information, 188

RetrieveComputerSystem.vbs, 426

RetrieveWMISEttings.vbs, 425–426

ROUND function, 60

RSOP namespace, 188

Run method, 48–49

RunNetStat.vbs script, 50–51

Running properties, list, 233–234

Runtime engines, 13

S

SBSQueryHotFix.vbs, 205

Script(s) add documentation to, 13–14 add power to, 25–48

Do...Loop, 47

Do Until...Loop, 43–46

Do While...Loop, 37–43

For Each...Next, 26–31

For...Next, 31–37

While...Wend, 47–48 defined, 4 documenting, 355 embedding, in Web pages, 21 enhancing, 13–14

Structured Query Language

475 ensure correct path information for, 254 header information, 5–8, 15–16 how to run, 20–22 modify, 14–22 open existing, 4 output information, 12–13, 19–22 prevent choking, 13 promote code re-use within, 331 reference information, 8–9, 16–18 run, with named arguments, 92–93 run existing, 4 step-by-step exercises, 22–23 use Notepad to speed modification, 17 useful registry keys, 15 worker information, 9–11, 18–19

See also entries for individual scripts

Scripting interface, troubleshoot, 425

Scriptomatic, 422

Security event log, query, 216–219

Security issues

Distributed Component Object Model (DCOM), 419 provider, 419

Security permissions, modifying WMI moniker to include additional, 222–223

Security settings, WMI moniker, 214–220

Select Case statement, 69–74

Header information, 71 in logon script, 357–358 modify CPUType.vbs, 74–77

Output information, 72–74

Reference information, 71–72

Worker information, 72–74

sendKeys method, 49

SendTo menu, add Notepad to, 22

Server authenticated currently logged-on user, 15

ServersAndServices text file, 97–98

Service accounts identifying, 239 logging, 239–241

Service dependencies, 421

Service information, 15

Services, Taskmanager.exe view of, 338

Set command, 58–59, 91

SetInfo command, 273

SetPowerState method, 200

SetStringValue, 375

Simple Mail Transfer Protocol (SMTP) address, 252

Single dimension array, 97

Sleep command, 36

SmallBIOS.vbs, 208

Space () command, 35–36

Spacing, WMI properties and, 231

specialFolders method, 170

Spelling, 19, 38–39. See also Option Explicit

Split function, 106–107

SQL. See Structured Query Language (SQL)

476

StartTime function

StartTime function, 40

StdRegProv class, 372–373

StopService method, 46, 200

Structured Query Language (SQL), 210, 231

subCheckArgs subroutine, 86, 106

subLogging subroutine, 170–171

subRecursiveFolders subroutine, 180–181

Subroutine, 329–341 defined, 48, 191 call, 331–332 create, 332 create users and log results, 332–334 defined, 329 logging, 234–237, 345–347 use to perform logging, 343–345

SubRoutineScript.vbs, 331–332

"Subscript out of range," 84

subtree modifier, 295

SysInfo.vbs, 350

Sysvol share, in Active Directory, 352

T

TCP. See Transmission Control Protocol (TCP)

TCP/IP. See Transmission Control Protocol/Internet Pro­ tocol (TCP/IP)

Telephone settings, user, 279–280

"Tell me everything about everything" script, 227

Terminal Server settings, modify, 282

Text file

ADO to query, 309–311 array, combine WMI and, 98

Time zone, echoing, 205

Timer function, 41–43, 60

TimeZoneSolution.vbs, 205

Transact-SQL (T-SQL), 210

Transmission Control Protocol (TCP), 51

Transmission Control Protocol/Internet Protocol (TCP/

IP), 76

Transmission Control Protocol/Internet Protocol (TCP/

IP) address, 319–321

Troubleshoot WMI scripting general steps, 432–433 identify the problem, 419–420 obtain diagnostic information, 426–432 err tool, 429–430

MofComp.exe, 430–431 verbose WMI logging, 427–432

WMI log files, 428–429

WMIcheck, 431 test local WMI service, 420–424 dependencies, 421 scriptomatic, 422 service status, 422

WBEMtest.exe, 423–424

WMI Control tool, 420 test remote service, 424–425 test scripting interface, 425–426

Two-dimensional arrays, 101–103

Type mismatch error, 209

U

UBound, 94, 97–99

Underscore character, 89

Universal Naming convention (UNC) path, 176, 358

Unnamed arguments, 85–86

User ID property, 298

User name, used to log on to domain, 15

User profile settings

ADSI, 278

Terminal Server, 285–287

User telephone settings, 279–280

UserAccountControl, 262–263

Users, delete, using ADSI, 287–290

User’s home directory, 15

V

Variable(s) benefits of, 28–29 constants vs., 27–29 declare, 6–7 defined, 6 standard names, 335 tables of, 355

VB.NET, 7

vbNewLine command, 35–36

.vbs file, 21

VBScript, 6–7, 13 double-check, 20 to learn about WMI, 224 logon script, 353–358 operators, 238–239 subroutines in, 330

Verbose WMI logging, enable, 427

VideoAdapterRAM_HardCoded.vbs, 341

W

WBEM repository, 432

WbemPrivilege, 215–220

WBEMtest.exe, 423

Web page, embedding script in, 21

Web sites, use WMI to create, 399–402 whenTest.exe utility, 65

Where clause, 241–244

While Not Wend construction, 296, 316, 319

While Not...Wend loop, 322

While...Wend, 47

WmiTemplate.vbs template

477

WhileWendLoop.vbs script, 47–49

Win32_Environment, to learn about WMI, 224

Win32_NetworkAdapterConfiguration, 323–325

Win32_Printer, 381–382

Win32Printer class, use filter on, 386

WIN32Processor, SetPowerState method, 200

Win32_Share properties, 229–230

Win32WindowsProduct Activation, properties of, 203–

204

Windows 2000, OS version build number, 420

Windows Management Instrumentation (WMI), 422 accepting defaults, 208–214 alternate ways to connect to, 212 classes, 194–200 combine text file and, 98 connection string, 223 consumers, 188 create Web sites, 399–402

DCOM security, 432

Do Until...Loop, 45–46

Do While...Loop, 40–43, 61 echoing the time zone, 205 enable DHCP using, 320–321

For Each...Next, 26–27, 30–31, 102–103

For...Next, 34–37

If Then, 58–62

If...Then...Elself, 65–67 infrastructure, 188

Key property in, 232–233 listing providers, 192–193 merge ADSI and, 322–323 methods, 199–200 modify, 18–19 module registration, 432 moniker security settings, 214–220 move past dull arrays, 96–94 namespaces, 189–191 network and. See WMI-network connection objects, 189–191 properties, 197–199 query, 201–204, 227–247. See also WMI query read registry using, 377–378 resources, 188 retrieving Hotfix information, 204–205 script, 9–11

Select Case statement and, 70–71 service information, 198–199 service settings, 432

strComputer variable and, 64 troubleshoot, 420–439 two-dimensional arrays, 102–103 understanding the model, 188 use subroutine to retrieve service information from,

338–341 using multiple arguments, 89 using VBScript to learn about, 224 using Win32_Environment to learn about, 224

WBEM repository, 432

Windows NT, as Pascal-cased, 253

Windows Product Activation (WPA) information, 203–

204

Windows Scripting Host (WSH), 12–13, 21, 84–86

Windows Server 2003

Active Directory in, 298

OS version build number, 420

WMI in, 187–206

WMI namespaces in, 190

Windows XP

OS version build number, 420

WMI namespaces in, 189

winmgmts, 202–203

WinNT provider, 253

WMI. See Windows Management Instrumentation

(WMI)

WMI CIM Studio tool, 233

WMI classes, locate, for IIS 6.0, 395–397

WMI Control tool, 420, 424–425, 427

WMI database corruption, 419

WMI errors, common sources of, 419–420

WMI log files, 428–429

WMI logging, 433–437

WMI moniker additional security permissions, 222–223 alternate ways of configuring, 207 default, 220 to display machine boot configuration, 221–222

winmgmts as, 202–203

See also Moniker

WMI namespace, changes to Exchange, 407

WMI object browser, 213

WMI Platform SDK, 73

WMI query choosing specific instances, 237–238

Header information, 228–229 obtaining more direct information, 245–247

Output information, 229–230 in quotation marks, 217

Reference information, 229 selecting multiple properties, 231–237 selective data from all instances, 230–231

"tell me everything about everything", 227 using an operator, 238–241

Where clause, 241–244

Worker information, 229–230

WMI Query Language (WQL), 210, 231

WMI script, writing informative, 244

WMI service, test local, 420–424

WMIcheck, 431–432

WMI-network connection, 316–319

WmiTemplate.vbs template, 242

478

Worker information

Worker information, 272–273

ADO, 296–297

ADSI, 255–256

ADSI address tab script, 275–277 create ADSI users, 259–260 create users log, 336 create Web sites, 402

CreateMultiFolders.vbs, 167

EnableDHCP, 321

Exchange 2003, 410 filtered print monitor, 389

IIS 6.0 connection, 399 logon scripts and, 357–358 monitor printer status, 384–385 registry connection, 371–372 registry key, 374–375

WMI moniker, 209

WMI query, 229–230

WMI script, 203

WMI-network connection, 318–319

WorkWith2DArray.vbs, 101–102

WPA. See Windows Production Activation (WPA) infor­ mation

WQL. See WMI Query Language (WQL)

Write command, 60

WriteToRegKey.vbs, 376

WScript, 10

WScript.Arguments, 87

WScript.Arguments.Count method, 84–85

WScript.Arguments.Named, 90–91 to echo out value of strLine, 46

WScript.Echo command, 12, 20, 35, 36, 68, 84, 86, 97,

168, 172, 209, 318

WScript.Echo line, 99

WScript.exe, 13, 20

WScript.quit, 67

Wscript.shell object, 48–49, 170–171

WSH. See Windows Scripting Host (WSH)

WshNetwork class, 356

WshShell object, 170–171, 368–369

comspec variable, 368–369 define command, 369

advertisement

Was this manual useful for you? Yes No
Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Related manuals

Download PDF

advertisement