“Hey, Windows Guru. How can I make it so that my VBScript event routines are only executed after a certain point in my script?”
Sam, you’ve asked an awesome question that you probably won’t find much documentation for. However, I have a really cool solution for you.
As you probably know, VBScript event routines are executed asynchronously. That means that the VBScript engine is going to execute an event routine any time it receives an event notification while your script continues to run. That’s usually fine for most applications, but as you’ve mentioned, what do you do if you don’t want that event routine to execute after a certain point in your script?
Let’s take a minute to make sure everyone is up to speed on how events work in VBScript. In VBScript, objects can issue events whenever certain based on changes to that object or its environment. These events are hard coded into the object’s code and made available to programmers. For instance, Microsoft’s Word automation object can notify a script whenever a new document is created. Likewise, Internet Explorer’s automation object can notify you whenever a file download is complete.
In order to handle events in VBScript, you must first connect to the object that you wish to receive events from. To do this you must use the CreateObject or ConnectObject method from the WScript object. You will typically use the first.
Set objWord = WScript.CreateObject("Word.Application", "wd_") Sub wd_DocumentChange MsgBox "The current document has been changed." End Sub
This should look fairly standard to you. I’ve just created an object referent to the Word automation object. This effectively creates a running copy of the Word application. Notice that I’ve specifically used the WScript version of the CreateObject method rather than VBScript’s own native method to create the Word object. This allows me to use a second parameter to supply an alias for this object. This alias will be used to reference this object’s events. The alias follows the same naming rules as a variable reference and should end with an underscore.
Next, you create a subroutine named after the event you wish to monitor. In this case, I’m monitoring the DocumentChange event which will notify the script any time that changes occur within the current Word document. The event routine must be named specifically in the form of alias_eventname.
Once this object is created, any event routines attached to that alias will execute for their specified events. Let’s assume for a moment that we don’t actually want that to happen. What if we want to create the Word object and then start monitoring events later?
Set objWord = CreateObject("Word.Application") objWord.Visible = False objWord.DisplayAlerts = False objWord.Documents.Add Set objDoc = objWord.ActiveDocument objDoc.Content = "This is some text."
To do this, let’s revert to the common method of creating the Word object without an alias instead. This allows us to work with the Word application without handling any events. In this case, we’re creating a new document and then adding some text.
Here’s where it might come in handy to control when our events are handled. If we work of our previous examples and monitor document changes, we probably don’t want to know when our script is doing the changing. So now that we’ve added our text, let’s go ahead and create an event alias so that our event routine will begin working.
WScript.ConnectObject objWord, "wd_"
Remember that the ConnectObject method can be used to reference objects that already exist. Since we already created a reference to the Word object, we can use the ConnectObject method to add an alias to our existing object reference. Remember to use the WScript objects version of this method or you’ll get an error for having an extra parameter.
By adding an alias to our existing reference, we’ve effectively turned event handling on for that object.
Ok, this very simple, but it may seem like a lot to take in. Let’s take a look at a complete script so you can see better what the flow of the script will look like.
Const wdDoNotSaveChanges = 0 Set objWord = CreateObject("Word.Application") objWord.Visible = False objWord.DisplayAlerts = False objWord.Documents.Add Set objDoc = objWord.ActiveDocument objDoc.Content = "This is some text." WScript.ConnectObject objWord, "wd_" 'The event routine is now activated. Set objSelection = objWord.Selection 'Creating a selection should result in a DocumentChange event objDoc.Close objWord.Quit wdDoNotSaveChanges Sub wd_DocumentChange MsgBox "The current document has been changed." End Sub
This script demonstrates how you can enable an event routine later in a script by adding an alias to an object reference rather than at the time of its creation. So then, what if you wanted to turn that event routine back off again?
Set objWordAlias = WScript.ConnectObject(objWord, "wd_") ' Create an event alias on WScript.DisconnectObject objWordAlias ' Destroy the event alias without disconnecting the original object reference
To turn off an event alias, you can use the DisconnectObject method. In this case, you’ll want to supply an object name when creating the alias so that only the alias reference is disconnected.
Hope that helps!