Well hello again! Glad to see you've made it this far without giving up. In this, the fourth installment of my popular series, I'm going to cover functions and subroutines, what they are, and why they are useful. Just in case you stumbled onto the series in the middle, please take a few minutes and review the previous installments here:
So.. Now that we are once again on the same page, let's get to it.
Functions and subs are basically the same thing, with only a single difference: A function returns a value, but a sub does not. Chances are you've already used functions and subs without realizing it. When you say
GetObject is actually a function that returns the object you have given the ADSPath to. That function is one that is built-in, you don't actually see the code behind it.
But, what is a function? Why would I want one? What would I do with one? Well, imagine you had this list of numbers. You needed to take each number, multiply it by something else, then concatenate it to a string, and then echo what it is. You could go like this:
In the above code, the x in parentheses in the declaration line of the sub is the variable that will be passed in. That variable is only in scope while the function or sub is executing; as soon as the function or sub exits, the variable is destroyed. This is what is called a local variable. The above code, when executed, will provide identical output to the code listed above that (the one without a sub), but note how much more user friendly it is: If we wanted to add 4 or 5 or 6 to be processed, it would be only a single line of code, as opposed to three lines in the previous example. But now, how about we do something useful with it? Say you are writing a login script, and you are going to map network drives. Instead of saying:
...oNetwork.RemoveNetworkDrive "P:", True, TrueoNetwork.MapNetworkDrive "P:", "\\server\share", TrueIf Err.Number <> 0 then MsgBox "Error mapping drive. Please contact the administrator." Err.ClearEnd IfoNetwork.RemoveNetworkDrive "Q:", True, TrueoNetwork.MapNetworkDrive "Q:", "\\server\share2", TrueIf Err.Number <> 0 then MsgBox "Error mapping drive. Please contact the administrator." Err.ClearEnd IfoNetwork.RemoveNetworkDrive "R:", True, TrueoNetwork.MapNetworkDrive "R:", "\\server\share3", TrueIf Err.Number <> 0 then MsgBox "Error mapping drive. Please contact the administrator." Err.ClearEnd If
Notice above that for every drive you want to map, you need to add 6 more lines of code. That's very time consuming, and it makes for large files that are difficult to read. So, make it a sub!
Sub MapDrive(DriveLetter, NetworkPath) On Error Resume Next oNetwork.RemoveNetworkDrive DriveLetter, True, True oNetwork.MapNetworkDrive DriveLetter, NetworkPath, True If Err.Number <> 0 then MsgBox "Error mapping drive. Please contact the administrator." Err.Clear End IfEnd Sub
See how the only line of the function itself (not the declaration or the end) actually sets the name of the function to a value? That is how you return the value to the code that called the function. While that might be a pretty simple example, it illustrates the concept perfectly. Call it like this:
And get the same result. Again, how is this useful? Well, how about this function:
Function IsLocked(UserDN) Set oUser = GetObject("LDAP://" & UserDN) Set oLockout = oUser.Get("LockOutTime") If Err.Number = -2147463155 Then IsLocked = False Exit Function End If If oLockout.LowPart = 0 and oLockout.HighPart = 0 Then IsLocked = False Else IsLocked = True End IfEnd Function
Note that with functions, you can use parentheses when you call them, but with subs, you cannot. I don't know, some strange rules built into the language, that's just how it is. Since I prefer to use parentheses, I usually write all my subs as functions. Functions do not HAVE to return a value, it's simply that they can.
Next installment we'll cover recursion. That's when functions REALLY get fun. Until then...