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.

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].

comments powered by Disqus
Most   Popular