Keeping your scripts structured with procedures is great for organization and flexibility—but show caution in their use.
Get Yourself Organized, Part 2
Keeping your scripts structured with procedures is great for organization and flexibility—but show caution in their use.
- By Chris Brooke
- 08/01/2000
If you promise not to tell anyone, I’ll let you in on
a little secret: I’m not very organized. My desk has stacks
upon stacks of papers that I’m sure must be important
for something, I simply can’t remember what. Sure, if
anyone asks, I maintain that I have a unique filing system
and that I know where everything is. Truth is, it ain’t
so. Usually I’m lucky enough to find what I’m looking
for in the nick of time, but it’s just that: luck. How
is it, then, that I’m able to keep my scripts so organized?
Well, many years ago, after wading through pages and pages
of spaghetti code, I finally came to the realization that
I’d never get any scripts completed and debugged unless
I did a better job of organizing them. Procedures to the
rescue! Now, if I could just figure out a procedure for
finding my phone underneath one of these piles I might
be able to call my boss and tell him not to open that
“ILoveYou” email.
Last month,
we looked at how procedures (Subs and Functions) are able
to keep track of variables and components declared locally.
The most significant advantage to using procedures along
with locally-declared variables (aside from organization)
is reusability. So long as the procedure doesn’t rely
on any externally-declared variables, you can use it anywhere!
Let’s start by examining my solution to the homework I
assigned last month.
The Assignment: Write
a script to compare the “Date Last Modified” property
of two different files, using only one object.
The Solution: Simplicity
is its own reward…
' DateComp.vbs
' Compare DateLastModified property of two
' files using procedures
Option Explicit
Dim strFile1, strFile2
Main
WScript.Quit
Sub Main()
strFile1=GetFile("First")
strFile2=GetFile("Second")
If GetModDate(strFile1)=Empty
OR
GetModDate(strFile2)=
Empty Then Wscript.Quit
If GetModDate(strFile1)> GetModDate(strFile2)
Then WScript.Echo
strFile1
& "was modified
most recently."
Elseif GetModDate(strFile1)< getmoddate(strfile2)="">
WScript.Echo strFile2
& " was modified most
recently."
End If
End Sub
Function GetFile(File)
GetFile=InputBox(
"Enter the complete path and name of the "
& File & " file:", "Enter FileName")
End Function
Function GetModDate(strFile)
Dim objFSO, objFile
Set objFSO=CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(strFile)
Then
Set objFile=objFSO.GetFile(strFile)
GetModDate=objFile.DateLastModified
Else
GetModDate=Empty
End If
End Function
The only procedure that creates and uses the FileSystemObject
is the “GetModDate” function. By declaring the variables
and creating the objects inside the function, we can put
this routine in any script and be assured that we won’t
“step on” any variables or objects created elsewhere in
the script. Of course, we can add code to handle Empty
strings more elegantly than simply exiting the script,
but that’s the easy part. We’ve already learned how to
do that!
Don’t Overdo It!
I think now is as good a time as any to remind you to
be mindful of your resources. Objects, whether they’re
built-in Windows components or third-party tools, require
a certain amount of overhead. When you instantiate (CreateObject)
a component, it’s like assigning a value to a variable—a
potentially huge value! If you go off creating tons of
objects willy-nilly, you just might see your performance
dropping off.
As with all things, there’s a balance to be achieved
between maximum flexibility and maximum performance. While
keeping your scripts structured with procedures is great
for organization and flexibility, too many instantiations
of too many components can make your super-duper Pentium
III seem like a 486! If you find this happening to you,
here are some tips you can use in a pinch to get back
that performance edge.
First, go through your script and trim out all of the
“extra instantiations” that you can. If you’re using one
or two objects throughout your script, consider declaring
it in the main body, instead of inside procedures. You’ll
lose some of the reusability but gain back lost performance.
I know, this is completely contrary to what I just demonstrated
in the above script. Remember, that was to show you how
to create a reusable procedure that could operate independently
in any script. Good script management should include careful
evaluation of the task at hand to determine the most effective
solution. If the procedure is used all the time, you should
go ahead and create the object once and simply reference
its properties in the individual procedures.
Second, access intrinsic objects directly. As we’ve previously
discussed, many of the objects you’ll use in your scripts
are intrinsic, which means they’re automatically created
when you launch your script. Examples of these are the
ERR object and the WScript object (including the “Arguments”
collection). Instead of:
Dim objArgs, strArgs1, strArgs2
Set objArgs=CreateObject(WScript.Arguments)
strArg1=objArgs.Item(0)
strArg2=objArgs.Item(1)
Try this:
Dim strArgs1, strArgs2
StrArgs1=WScript.Arguments(0)
StrArgs2=WScript.Arguments(1)
This solution helps reduce the number of objects created
but can cause extra coding if you use it a lot. (In the
example above it actually shortened the script, but that’s
misleading. Trust me, you’ll get tired of typing if you
access intrinsic objects in this manner all the time.)
Again, there’s a balance to be achieved. If your script
performs a great deal of logic against the component,
assigning it to a variable is the way to go. On the other
hand, if you simply need to retrieve one or two properties,
consider accessing the object directly.
“Get” This!
Thus far, we’ve been gaining access to built-in and third-party
components by either using “CreateObject” or by executing
a method of one object that creates another. There’s another
way of gaining access to certain components: “Get Object”.
GetObject returns a reference to an existing object (one
that has already been instantiated). This method of accessing
a component is perhaps best demonstrated by the Active
Directory Services Interface. In fact, GetObject is the
only way to gain access to the resources exposed by ADSI.
Over the next few months we’re going to take a good,
hard look at ADSI and how we can use it to perform a plethora
of useful administrative tasks. Since we’ll be starting
this new topic next month, I’m not assigning any homework
today. Take a break—you’ve earned it!
Now if you’ll excuse me, I have to find a shovel… I think
I hear my phone ringing.
About the Author
Chris Brooke, MCSE, is a contributing editor for Redmond magazine and director of enterprise technology for ComponentSource. He specializes in development, integration services and network/Internet administration. Send questions or your favorite scripts to [email protected].