Hello again, all. For those of you that have been following along, you'll know that this is my third article on this topic (though it is not Part III). This article is sort of remedial, and probably the topic with which I should have started the series. VBScript For Windows System Administrators Part 1 VBScript For Windows System Administrators Part 2
So... Why am I calling this the missing prequel, and "What's with the myths?" you may be wondering? Well, from reading code on here, and seeing code that peers have written, and from seeing code that pupils have written (I've taught dozens of employees & co-workers how to code), I've seen lots of good things, and lots of not-so-good things. This article will focus more on the latter.
MYTH 1. VARIABLES MUST BE DECLARED WITH DIM IN VBS.
The fact of the matter is that VBS is an extremely flexible scripting language, and will create variables on the fly. For example, simply saying:
x = 8
creates a variable called "x" and assigns it an integer value of 8. The only exception to this is if "Option Explicit"
is used. In that case, you MUST DIM all variables. This is useful when you are writing VERY large scripts, and want to eliminate typos. How is this useful? Since VBS will happily create variables for you as you use them, consider:
VariableA = 24
VariableB = 24
VariableC = VariableA + VaraibleB
The answer you would get is 24. Why? Because on the "VariableC =" line, VariableB is not spelled correctly. The programmer made a typo. But, since Option Explicit was not used, VBS simply created a new variable right there, said that it had no value, and so VariableC was assigned a value of 24.
A related mistake (though not really a myth, since it's not allowed in the language) is trying to declare the type of the variable in the dim statement.
Dim x as Integer = 8
While that might be perfectly valid in VB.NET, in VBS, it is not. VBS only has a single variable type, called a variant. With this single variable type, we can store any data we want.
x = 8
x = "baseball"
x = 3.14159
Those three lines, when executed together in a single script, are perfectly valid. While not really doing anything useful on their own, it illustrates the concept that we can store anything in a single variable. Above we have an integer, a string, and a double. What if we want the variable to be typed? Well, we can sort of "force it", but only temporarily. This is done using the various Cast functions that are built into the language.
x = CInt("8")
would take the string "8" and cast it to an integer.
x = CDbl("3.14159")
would take the string 3.14159 and cast it to a double.
x = CStr(3.89)
would take 3.89 and cast it to a string.
Why is this useful? Well, certain types of built-in functions expect input of a certain type. Additionally, certain types of object properties must be presented in a specific format. 8 is an integer, while "8" is a string. They will both appear identically when you echo them or display them in a MessageBox, but they are very different. Refer to Part 2 for an example of Active Directory properties of users and the types of value they expect to be passed.
MYTH 2. ALL VARIABLES MUST BE SET TO NOTHING AT THE END OF THE PROGRAM
This is a hold-over from days of old, in programming languages like C, C++, and many others. The reason for it is that these older (and more complex) languages did NOT have automatic garbage collection. WSH (Windows Script Host, the interpreter that runs VB Scripts) DOES. Let me repeat that. WINDOWS SCRIPT HOST HAS AUTOMATIC GARBAGE COLLECTION. What does that mean? Well.. Have you ever noticed how when you freshly reboot your computer it runs better for a while, until it's been running for a few days again? Have you ever heard a friend or co-worker use the term "Memory Leak"? That's exactly what it is.
I remember being in college (I was a CS major), sitting in my first semester C++ class. The teacher was explaining about memory leaks. Essentially, what happens is this: When you create a variable in C++, it grabs a piece of memory large enough to hold the data that you said that variable would hold. This is done with the constructor. Now, when the program terminates, the destructor has to be called to release that memory back to the computer. If this does not happen, then when the program terminates, (since C++ can directly access the computer's memory,) the memory will not be "released", and the operating system will not use it, nor will it allow another program to access it as it thinks the program is still using it.
Picture it as returning a library book without checking it back in. The resource is physically in the building, but the computer shows that it is not available, so no one will go to look for it. If you have 128MB of memory, but your program consumes 2MB and never releases it, then after running it 14 times, you are down to 100MB of usable memory. When you reboot the computer, the "reservations" in the OS that are holding that memory are released, and so all 128MB is once again available.
WSH does this automatically for you. It keeps track of every variable that is created, and when the script terminates, before WSH destroys the environment, it releases all handles on system memory. As such, the use of
Set blahblah = Nothing
is not necessary in VBS. The only thing it does is make your code longer and waste precious keystrokes.
Let's face it, we got into IT because we're lazy, and enjoy desk jobs that allow us to work with our minds. Manual labor? As if! Typing is the closest I get to manual labor, and if I can limit the number of keystrokes or mouse-clicks necessary to accomplish a task, then I am more efficient, and I can accomplish tasks more quickly, thus leaving me more time to read EE and Slashdot.
MYTH 3. YOU SHOULD ALWAYS USE "ON ERROR RESUME NEXT" IN YOUR CODE.
Why? Because then you never know where the errors are! Consider you start your script with "On Error Resume Next" and then you try to assign a string value to an AD user property that expects an integer value. You run the script and it does not generate any errors, but when you go view the user in AD, the value is not there. Well, had you not used "On Error Resume Next", you would have seen the Type Mismatch error, and you would have been able to correct it.
Now, this is not to say that you should not ever use "On Error Resume Next". AFTER a script is written and debugged to the best of your ability, *if* it is going to be an automated process, or something that should in no way interact with a user (like a login script), then go ahead and use it. Another situation it's useful is if you want to code error handling into your script.
Set oFS = CreateObject("Scripting.FileSystemObject")
Without "On Error Resume Next", if the source file didn't exist, or we didn't have permissions to get to the location we were trying to copy to, we would see the error generated, and the script would stop running. However, if we add "On Error Resume Next", the error would never be thrown, but we also wouldn't know if the file was successfully copied. How do we handle this?
On Error Resume Next
Set oFS = CreateObject("Scripting.FileSystemObject")
Set oFile = oFS.CreateTextFile("c:\copyFile.log")
If Err.Number <> 0 Then
oFile.Writeline("Error copying " & sourcefile)
Now we have a nice piece of code that can be scheduled to run, and will either perform it's intended task, or will write to a log file if it encounters an error. Want to know what the error was? Err.Description will tell you, but we'll cover error handling more in-depth in a later article.
MYTH 4 (not specific to VBS). NO ONE CARES WHAT MY CODE LOOKS LIKE, AS LONG AS IT WORKS.
FALSE, FALSE, F A L S E !!!
I cannot stress that enough. Your code needs to be legible, it needs to make sense, people need to be able to read it.
Just because you CAN use anything for a variable name does not mean it is a good idea to do so. For example, when I was in college, the professor told us that we could use anything we wanted for a variable name, since no one would see our code once it was compiled, and the consumer wouldn't know what the variable names were. So, every single project I turned in to that professor had the same two variables in it (plus many others, but these were my "signature"): "a**hole", and "george." Now, as a professional, imagine a coworker or a supervisor or manager reviewing your code and seeing a line that looks like this:
For Each a**hole in CustomerDatabase
I don't imagine that discussion would go well. Likewise, don't name everything a b c d e f just for the sake of saving keystrokes. It becomes a nightmare to follow what each of those things are, so use descriptive variable names. If the variable will hold an employee's name, then call it something like empName.
Along these same lines, if your code looks ugly to you or a coworker, imagine how the system looks at it. Sure, sure, you're thinking "But it's only 10 lines, quick and dirty"
. That's a very bad habit to get into. What if you write a recursive function, but write it poorly? Then it calls itself 1000 or 10000 times. Well, now that short, 10-line, poorly written function is going to run, poorly, 1000 or 10000 times. Always get in the habit of writing code the most efficient, effective way possible. That way, when you write code that will run automatically at scheduled dates/times, and a coworker is also sharing that same server to run his automated processes, there will be enough processor time for both of you.
Ok, ok, fine. Don't care about your coworkers, huh?
Then how about this: I learned VBS over 10 years ago. When I look back at some of the scripts I wrote in the beginning, I often find myself wondering "What the HECK was I thinking?!?" It could have been written so much more efficiently, or written so it was easier to understand. YOU
will eventually have to go back and revisit old code you have written. Trust me, after 6 or 8 months in production of not touching it, you'll forget exactly how it works, and you may as well be reading code written by someone else. So write it well the first time, and make it easy to understand.
Comments in code? My opinion is this: If it was hard to write, it should be hard to understand (meaning that your grandmother couldn't pick it up and tell you what it does). BUT -- the variable names and functions and subs should be well-written enough that someone who *is* a programmer can pick it up and follow along without the need for comments.
It's been my experience that in interpreted languages like VBS, if there are a lot of comments, then people who have NO BUSINESS modifying code open it up, think they understand, and make some change that usually makes things far, far worse, as opposed to better.
So, keep these things in mind and you'll be well on your way towards writing code that is not only useful, but fast and easy to understand when modification time comes (and trust me, it ALWAYS does).