Previous Section Table of Contents Next Section

What Are Variables?

Variables are temporary storage areas for data. You may even remember them from algebra: x + 5 = 10, solve for variable x. Of course, in those situations, x wasn't really a variable, because it always equaled some fixed amount when you solved the equation. In scripting, variables can change their contents many times.

graphics/arrow.gif Sample Script

Listing 5.1 shows a sample script. It's a fully functional script that will connect to a domain, locate any inactive user accounts, and disable them.

NOTE

Once more, I'm showing you a script that uses some advanced features. This lets me show you functional, useful scripts rather than dumbed-down examples, but for now I'm just going to explain the bits that are important for this chapter. I promise you'll get to the rest later!


Listing 5.1. DisableUser.vbs. We'll use this script as a running example throughout this chapter.

Dim sTheDate

Dim oUserObj

Dim oObject

Dim oGroupObj

Dim iFlags

Dim iDiff

Dim sResult

Dim sName

Const UF_ACCOUNTDISABLE = &H0002



' Constant for Log file path

 Const sLogFile = "C:\UserMgr1.txt"



' Point to Object containing users to check

Set oGroupObj = GetObject("WinNT://MYDOMAINCONTROLLER/Users")



On Error Resume Next

For Each oObject in oGroupObj.Members



 ' Find all User Objects Within Domain Users group

 ' (ignore machine accounts)

 If (oObject.Class = "User") And _

  (InStr(oObject.Name, "$") = 0) then Set oUserObj = _

  GetObject(oObject.ADsPath)



  ' get last login date

  sTheDate = UserObj.get("LastLogin")

  sTheDate = Left(sTheDate,8)

  sTheDate = CDate(sTheDate)



  ' find difference in week between then and now

  iDiff = DateDiff("ww", sTheDate, Now)



' if 6 weeks or more then disable the account

  If iDiff >= 6 Then

   iFlags = UserObj.Get("UserFlags")

  End If



  ' if the account is not already disabled...

  If (iFlags And UF_ACCOUNTDISABLE) = 0 Then



   ' disable account

   oUserObj.Put "UserFlags", iFlags Or UF_ACCOUNTDISABLE

   oUserObj.SetInfo



   ' Get user name and write a log entry

   sName = oUserObj.Name

   sResult = Log(sName,iDiff)



  End If



 End If

Next



' Release object

Set oGroupObj = Nothing



Function Log(oUser,sDate)



' Create a FileSystemObject

 Dim oFS

 Set oFS = CreateObject("Scripting.FileSystemObject")



 ' Create a TextStream object

 Dim oTextStream

 Set oTextStream = objFS.OpenTextFile(sLogFile, 8, True)



 ' Write log entry

 oTextStream.WriteLine("Account:" & vbTab & oUser & vbTab & _

 "Inactive  for:" & vbTab & strdate & vbatb & "Weeks" & _

 vbtab & "Disabled on:" & vbTab & Date & vbTab & "at:" & _

 vbTab & Time)



 ' Close file

 oTextStream.Close



 ' Release objects

 Set oFS = Nothing

 Set oTextStream = Nothing



 Log = True



End Function

Before you can run this script, you'll need to make two important changes.

  • Change MYDOMAINCONTROLLER to the name of an actual domain controller in your domain.

  • Change C:\UserMgr1.txt to the path and filename of the log file that you want the script to create.

NOTE

Note the use of the underscore (_) character at the end of some lines of text. Because the pages of this book are only so wide, I can't include very long lines of code. Instead, I break those lines up by using the underscore character. When you type this code, you can just skip right over the underscore and type the code as one long line. However, VBScript understands that the underscore is a line continuation character, so if you do type the underscore and keep the code on multiple lines, VBScript will understand perfectly. Try it both ways and see which one you like; I prefer to keep the underscore because it means I don't have to scroll to the right in my script editor to see the entire line of code.


This script logs in to the domain using the user credentials of whatever user runs the script; in order for it to work, of course, that user needs to be a member of the Domain Admins group. The script locates all users that haven't logged in for at least six weeks, disables their accounts, and writes an entry to the specified log file for your review.

NOTE

There's a lot going on in this script that I won't be explaining right away. I'll be using this script, along with a couple of others, as a running example through the next few chapters. Eventually, I'll explain everything in it. In the meantime, though, feel free to use it both as a working tool in your environment and as a great example of administrative scripting.


Declaring Variables

One of the first things you see in the DisableUsers script is the variable declarations.


Dim sTheDate

Dim oUserObj

Dim oObject

Dim oGroupObj

Dim iFlags

Dim iDiff

Dim sResult

Dim sName

Const UF_ACCOUNTDISABLE = &H0002

The Dim statements tell VBScript that you're defining, or declaring, a variable. Actually, Dim is short for dimension, a term that hearkens back to the early days of computing. Following each Dim statement is a variable name. Each of these statements tells VBScript to set aside room in memory for the variable, and to remember the variable's name.

Variable names must follow a few basic rules.

  • They are not case-sensitive. For example, sTheDate and sthedate are treated the same.

  • They must begin with a letter or an underscore (_) character.

  • They may contain letters, underscores, and numbers.

  • VBScript allows quite long variable names, but practically speaking they shouldn't be more than a dozen characters or so, or your script will become difficult for other people to read.

You may also notice the Const statement, which is short for constant. Constants are like variables in that they assign a meaningful name to an arbitrary value. In this case, the constant name UF_ACCOUNTDISABLE is a bit easier to remember than the hexadecimal value 02. However, unlike variables, constants-as their name implies-don't change. If you try to assign a different value to UF_ACCOUNTDISABLE during the course of the script, you'll receive an error message.

You need to understand that VBScript doesn't require you to define variables up front. In fact, you could delete every single Dim statement from this script and it would still work perfectly. So why bother?

One of the biggest causes of bugs in scripting is simple mistyping. For example, consider the following snippet of code from the DisableUsers script.


' get last login date

sTheDaet = UserObj.get("LastLogin")

sTheDate = Left(sTheDate,8)

sTheDate = CDate(sTheDate)

Notice anything peculiar? In the second line of code, I changed sTheDate to sTheDaet. Because VBScript doesn't require me to declare my variables up front, this line of code won't generate an error. Instead, VBScript will dynamically create a brand-new variable named sTheDaet on-the-fly. Of course, the third line of code assumes that the second line of code put some data into sTheDate, not sTheDaet, and so the third line of code won't work correctly. It still won't generate an error, but sTheDate will contain no data. Finally, the last line of code will generate an error-despite the fact that there's nothing wrong with the last line of code. The problem is all the way back in the second line of code where a simple typo created a new variable and introduced a serious logic error into the script.

Typos like this are easy to make and all too common. To help combat them, VBScript provides Option Explicit, a command you can add to the beginning of your script.


Option Explicit

Dim sTheDate

Dim oUserObj

Dim oObject

Dim oGroupObj

Dim iFlags

Dim iDiff

Dim sResult

Dim sName

Const UF_ACCOUNTDISABLE = &H0002

With Option Explicit in place, VBScript will require all variables to be declared before they can be used. Now suppose I were to rerun the script with the typo in the variable name.


' get last login date

  sTheDaet = UserObj.get("LastLogin")

  sTheDate = Left(sTheDate,8)

  sTheDate = CDate(sTheDate)

VBScript would generate an error on the second line of script, because I'm attempting to use a variable that hasn't yet been declared. That's exactly where I want VBScript to generate an error, too, because it's the line of script that actually contains the error.

TIP

Always include Option Explicit in your scripts. For brevity, I won't always include the line in the sample scripts in this book, but it's a great way to avoid spending hours to track down a typo.


Understanding Data Types

If you've worked with other programming languages, you may be familiar with the concept of data types. Simply put, there are different kinds of data in the world around us: numbers, letters, dates, huge numbers, pictures, and more. Most programming languages need to understand what kind of data a variable will contain, so that the language can treat the variable appropriately. For example, it wouldn't make sense to try to subtract the word Hello from a picture of a flower, and so most programming languages won't allow you to perform mathematical operations with anything but numeric variables. Languages that care about the type of data a variable will hold are called strongly typed languages.

VBScript, on the other hand, is weakly typed. You'll notice that none of the variable declarations include any hint as to the data type each variable would hold.


Dim sTheDate

Dim oUserObj

Dim oObject

Dim oGroupObj

Dim iFlags

Dim iDiff

Dim sResult

Dim sName

Const UF_ACCOUNTDISABLE = &H0002

There's no clue because VBScript only has one data type: variant. The variant data type can hold any kind of data, and that data can even change to a different type as your script runs. For example, the following snippet of code would be perfectly valid in VBScript.


Dim vData

vData = 1

vData = "Hello"

vData = Date()

You may think that this weakly typed stuff is great. After all, you can just pop any kind of data you like into a variable and VBScript won't care. In some ways, that's true; not having to worry about data types can be a time saver. On the other hand, as you'll see shortly, it can also be a real pain in the neck.

Assigning Data to Variables

You've already seen several examples of how to assign data to a variable. Here's a section of the DisableUsers script, with the data assignment lines highlighted in boldface.


' get last login date

  sTheDate = UserObj.get("LastLogin")

  sTheDate = Left(sTheDate,8)

  sTheDate = CDate(sTheDate)



  ' find difference in week between then and now

  iDiff = DateDiff("ww", sTheDate, Now)

This actually looks a lot like the old algebra class, right? The variable name appears on the left side of the equal sign (=), which is referred to as the assignment operator. Whatever you want inserted into the variable appears on the right side of the assignment operator. In all four of these examples, the variable is being filled with the results of a function, which I'll cover later in this chapter.

The right side of the assignment operator can include any kind of operation that results in a single value. So all of the following commands are legal.


Dim vVariable

vVariable = 1

vVariable = 1 + 1

vVariable = "Hello"

vVariable = Date()

Variables can also be assigned to each other. This makes sense if you consider variables as simply a representation of a value; assigning one variable to another simply copies the value.


Dim vVar1

Dim vVar2

vVar1 = 1

vVar2 = 2

vVar1 = vVar1 + vVar2

After running this brief chunk of script, vVar1 will contain the value 3.

Data Coercion

As I've already mentioned, VBScript doesn't much care what kind of data you put into a variable. However, there are certain operations that only support certain data types, so you can run into trouble. For example, consider the following operations and see if you can predict their output.


Dim vVar1

Dim vVar2

Dim vVar3

vVar1 = 1

vVar2 = "1"

vVar3 = "2"



MsgBox vVar1 & vVar2

MsgBox vVar1 + vVar2

MsgBox vVar1 - vVar2

MsgBox vVar2 + vVar3

NOTE

The MsgBox statement will display a small dialog box with the result of whatever operation you've given it. It's an easy way, in an example like this, to see how VBScript treats each operation.


If you type this script in and run it, you'll get four message boxes. They might not be what you expect! You should see an 11, a 2, a 0, and a 12. Can you guess why?

When you assign data to a variable, VBScript actually does care. It keeps track of what it thinks the data type is, based on what you gave it. For example, any number not included in quotes is definitely numeric data, without question. Anything in quotation marks is text, called a string. However, if the text is all numeric, VBScript acknowledges that it could be numeric data, not a string. Here's what happens.

  • The first operation uses the concatenation operator (the ampersand). This operator is only used to tack one string onto another string. VBScript knows this, and so it coerces, or temporarily converts, vVar1-which was a numeric value-into a string so that the operation will work. The result is a 1 being tacked onto another 1, for a result of 11.

  • The second operation seems to be adding a numeric value and a string. This doesn't make any sense, of course. However, in this case, VBScript can coerce the string data into a number, and it does so. The addition operation works smoothly from that point, with the result of 2.

  • The third operation requires a similar coercion to complete the subtraction operation and arrive at the correct result of zero.

  • The fourth operation is more interesting. Back before Microsoft added the ampersand as a concatenation operator, the plus (+) operator did double duty: For numbers, it was addition. For strings, it handled concatenation. Modern VBScript knows this, so when it sees two string values being "added" together, it concatenates them instead, giving you a result of 12.

Order isn't important to how VBScript tries to coerce data. For example, let's modify our sample script as follows:


Dim vVar1

Dim vVar2

Dim vVar3

vVar1 = 1

vVar2 = "1"

vVar3 = "2"



MsgBox vVar2 & vVar1

MsgBox vVar2 + vVar1

MsgBox vVar2 - vVar1

MsgBox vVar3 + vVar2

Rerun the script. Do you see any differences in the results? You shouldn't. VBScript prefers to use + as an addition operator, so it will try to do so when any of the involved values is numeric. However, in the last operation, where both values were set up as strings, VBScript gives in and performs concatenation.

What can you do to make sure VBScript treats your data the way you want?

  • Keep track of the data types you put into variables. I do this with the first letter of the variable name: S tells me it's a string, i is for integers, d for dates, b for Boolean values (True or False), and so forth. You can use my naming scheme or make up your own.

  • VBScript includes data conversion functions, which you'll learn about in Chapter 7. These functions can force data into a specific data type.

  • Avoid using the ambiguous + operator for concatenation. Instead, use the dedicated ampersand (&) and save the + operator for addition.

    Previous Section Table of Contents Next Section