Microsoft® Windows® 2000 Scripting Guide
Like subroutines, functions provide a way for you to use one section of code multiple times within a script. Unlike subroutines, however, functions are designed to return a value of some kind. This is not necessarily a hard-and-fast rule; VBScript does nothing to ensure that a function always returns a value and that a subroutine never returns a value. However, the scripting language is designed to make it easier to return values using functions.
In fact, when you create a function, VBScript automatically declares and initializes a variable that has the same name as the function. This variable is designed to hold the value derived by the function. Although there is no requirement that you use this variable, doing so makes it very clear that the value in question was derived by the function of the same name.
For example, the following script includes the statement Wscript.Echo ThisDate. ThisDate also happens to be the name of a function that retrieves the current date. In this script, notice that:
The Wscript.Echo statement actually performs two tasks.
First it calls the function ThisDate. The function, in turn, sets the value of the special variable ThisDate to the current date.
After the function has completed, Wscript.Echo then echoes the value of this special variable.
Option Explicit is used, and the variable ThisDate is never declared. However, no error occurs because VBScript internally declares and initializes this function variable for you.
Option Explicit Wscript.Echo ThisDate Function ThisDate ThisDate = Date End Function
Note that this approach works only for a function, and not for a subroutine. The following code generates a run-time error because VBScript is unable to assign the date to the name of a subroutine:
Wscript.Echo ThisDate Sub ThisDate ThisDate = Date End Sub
Passing Parameters to Functions
Functions are often used to carry out a mathematical equation and then return the result of this equation. For example, you might use a function to convert bytes to megabytes or convert pounds to kilograms.
For a function to carry out a mathematical equation, you must supply the function with the appropriate numbers. For example, if you want a function to add the numbers 1 and 2, you must supply the functions with those two values. The numbers 1 and 2 are known as parameters (or arguments), and the process of supplying a function with parameters is typically referred to as passing those values.
To pass parameters to a function, simply include those values in the function call. For example, this line of code calls the function AddTwoNumbers, passing the values 1 and 2:
AddTwoNumbers(1 , 2)
In addition to including the parameters within the function call, the function itself must make allowances for those parameters. This is done by including the appropriate number of variables in the Function statement. This line of code, for example, creates a function that accepts three parameters:
Function AddThreeNumbers(x, y, z)
If the number of parameters in the Function call does not match the number of parameters in the Function statement, an error will occur. For example, this script generates a "Wrong number of arguments" error. Why? Because two values are passed to the function, but the Function statement does not allow for any parameters:
x = 5 y = 10 Wscript.Echo AddTwoNumbers(x, y) Function AddTwoNumbers AddTwoNumbers = a + b End Function
To correct this problem, include space for two parameters within the Function statement:
x = 5 y = 10 Wscript.Echo AddTwoNumbers(x, y) Function AddTwoNumbers(a, b) AddTwoNumbers = a + b End Function
You might have noticed that the parameters used in the Function call (x and y) have different names from the parameters used in the Function statement (a and b). VBScript does not require the parameter names to be identical; if it did, this would limit your ability to call the function from multiple points within a script. (Although this would be possible, you would always have to assign new values to variables x and y before calling the function. This could be a problem if you did not want to assign new values to x and y.)
Instead, VBScript simply relies on the order of the parameters. Because x is the first parameter in the function call, the value of x is assigned to a, the first parameter in the Function statement. Likewise, the value of y, the second parameter in the Function call, is assigned to b, the second parameter in the Function statement.
To show how a function might be used in an actual system administration script, the following sample retrieves the amount of free disk space on drive C of a computer and then calls a function named FreeMegabytes. This function converts the free space from bytes to megabytes and returns that value. This new value is then echoed to the screen:
Set objWMIService = GetObject("winmgmts:") Set objLogicalDisk = objWMIService.Get("Win32_LogicalDisk.DeviceID='c:'") Wscript.Echo FreeMegaBytes(objLogicalDisk.FreeSpace) Function FreeMegabytes(FreeBytes) FreeMegabytes = FreeBytes / 1048576 FreeMegabytes = Int(FreeMegabytes) End Function
Note when working with functions that each time VBScript sees the name of a function, it will attempt to call that function. This means that even though there is a special variable named, in this case, FreeMegabytes, you do not have access to that variable except when calling the function. For example, in the following script, the FreeMegaBytes function is called, and the free space displayed. In the next line, the script then attempts to echo the value of the FreeMegabytes variable.
Set objWMIService = GetObject("winmgmts:") Set objLogicalDisk = objWMIService.Get("Win32_LogicalDisk.DeviceID='c:'") Wscript.Echo FreeMegaBytes(objLogicalDisk.FreeSpace) Wscript.Echo "Free space: " & FreeMegaBytes Function FreeMegabytes(FreeBytes) FreeMegabytes = FreeBytes / 1048576 FreeMegabytes = Int(FreeMegabytes) End Function
When the script runs, the error message shown Figure 2.25 appears. This happens because VBScript does not echo the value of the FreeMegaBytes variable. Instead, it tries to call the function FreeMegaBytes. This call fails because the function requires you to supply the number of free bytes.
Figure 2.25 Error Message for Improperly Accessing a Function Variable
If you need to refer to the value derived from a function without calling that function, save the value in a separate variable. For example, in this script, the value returned from the FreeMegabytes function is saved in the variable AvailableSpace. This variable can be used at any time without calling the function.
Set objWMIService = GetObject("winmgmts:") Set objLogicalDisk = objWMIService.Get("Win32_LogicalDisk.DeviceID='c:'") AvailableSpace = FreeMegaBytes(objLogicalDisk.FreeSpace) Wscript.Echo "Free space: " & AvailableSpace Function FreeMegabytes(FreeBytes) FreeMegabytes = FreeBytes / 1048576 FreeMegabytes = Int(FreeMegabytes) End Function
Passing Parameters by Value or by Reference
The values passed to a function are rarely hard-coded into a script; instead, values are typically passed to a function by using a variable. For example, the following two lines of code set the value of the variable x to 100 and then pass the variable to a function named ModifyValue:
x = 100 Wscript.Echo ModifyValue(x)
The value of x at the time the function is called is 100. The value of x at the time the function finishes running depends on two things: whether the function actually modifies the value in some way and whether the function was called by value or by reference.
To explain the difference between passing variables by value or by reference, consider the following script, which sets the value of x to 100 and then, within the function itself, changes the value of x to 99:
x = 100 Wscript.Echo ModifyValue(x) & VbTab & x Function ModifyValue(x) ModifyValue = x / 25 x = 99 End Function
When the preceding script runs, the message box shown in Figure 2.26 appears. As you can see, the variable x was divided by 25 and then was reassigned the new value 99.
Figure 2.26 Assigning a New Value Within a Function
In many scripts, the fact that the function changed the value of x makes no difference. However, what if you need to use the original value of x later in your script? In that case, the fact that the function changed the value of x makes a very big difference.
By default, VBScript passes variables by reference. This means that the function receives a reference to the variables location in memory, and thus performs its calculations using the variable itself. Depending on the function, this can change the value of the variable.
To ensure that your variables are not changed by a function, pass the variables by value. With this approach, VBScript does not pass a reference to the actual variable; instead, it merely passes the value of that variable. Because the function does not have access to the variable itself, it cannot change the value of that variable.
To pass a variable by value, include the ByVal keyword within the name of the function. For example, this script passes the variable x by value to the function ModifyValue:
x = 100 Wscript.Echo ModifyValue(x) & VbTab & x Function ModifyValue(ByVal x) ModifyValue = x / 25 x = 99 End Function
When the preceding script runs, the message box shown in Figure 2.27 appears. Notice that the value of the variable x remains unchanged, even though the function appears to have set the value of x to 99. What really happened is that the function set the value of a copy of x to 99. Within the function itself, x now equals 99. As soon as the function ends, however, this temporary copy of x disappears. Meanwhile, the real x has retained its original value.
Figure 2.27 Passing a Variable by Value
You can pass some variables to a function by value and other variables to the same function by reference (using the ByRef keyword). For example, this line of code passes the variable x by value and the variable y by reference:
Function TestFunction(ByVal x, ByRef y)
In this function, it is possible for the value of y to be changed after the function finishes. However, the value of x will remain unchanged.