1

I have a fairly large VB Script project in which the primary script "includes" a number of "libraries" using the standard trick of reading file contents and running ExecuteGlobal on them. Some of the libraries are pretty vast and written by various third parties.

I want to use Option Explicit. If I make it the first line executed, however, some of those libraries blow up. But, if I move the directive to below my list of includes, I encounter the error Expected Statement on that line. Even more confusing, if Option Explicit appears at the top of one of the libraries (in the middle of the list of them), all is well. But, I wanted to remove (or comment that out) from any of the libraries and only enforce the restriction in my implementation script.

What's the rule about where Option Explicit must appear? Does it have to be the first line or not? Why is it kosher for it to not be the first line when I apply it via an "include"? How can I achieve my objective?

Code Examples:

Option Explicit  ' CAUSES RUNTIME ERROR IN A LIBRARY

Sub Include( sRelativeFilePath )    
    Dim oFs : Set oFs = CreateObject("Scripting.FileSystemObject")
    Dim sThisFolder : sThisFolder = oFs.GetParentFolderName( WScript.ScriptFullName )
    Dim sAbsFilePath : sAbsFilePath = oFs.BuildPath( sThisFolder, sRelativeFilePath )
    ExecuteGlobal oFs.openTextFile( sAbsFilePath ).readAll()
End Sub
Include ".\SomeLib.vbs"
Include ".\SomeOther.vbs"
Include ".\YetAnother.vbs"

Vs

Sub Include( sRelativeFilePath )    
    Dim oFs : Set oFs = CreateObject("Scripting.FileSystemObject")
    Dim sThisFolder : sThisFolder = oFs.GetParentFolderName( WScript.ScriptFullName )
    Dim sAbsFilePath : sAbsFilePath = oFs.BuildPath( sThisFolder, sRelativeFilePath )
    ExecuteGlobal oFs.openTextFile( sAbsFilePath ).readAll()
End Sub
Include ".\SomeLib.vbs"
Include ".\SomeOther.vbs"
Include ".\YetAnother.vbs"

Option Explicit  ' CAUSES COMPILATION ERROR 
BuvinJ
  • 10,221
  • 5
  • 83
  • 96
  • What do you mean by "some of the libraries blow up"? Not clear what the problem is, so not easy to try and help. FYI, you want `Option Explicit` as the first line in the main script and also at the top of each library. – Dave Apr 18 '18 at 14:45
  • I posted some example code. By "blow up" I mean run time errors encountered when using them. I can't apply Option Explict to large third party libraries that were not written with that restriction unless I want to waste piles of time tweaking them as I encounter such run time errors. – BuvinJ Apr 18 '18 at 14:48
  • 2
    Worth having a look here: https://stackoverflow.com/questions/17316186/look-ma-i-can-redefine-global-variables-even-with-option-explicit-active-but – Dave Apr 18 '18 at 14:53
  • `Option Explicit` needs to be the first element in your `vbscript` if you're going to use it - but if that then causes your libraries to throw errors because they were written with undeclared variables etc then your only option may be to execute without the option set, or update the libraries. – Dave Apr 18 '18 at 14:54
  • Thanks for the link! I believe that does explain what I'm seeing. `Option Explicit` is apparently applied within the `Execute Global` "context" when placed in a library, but that does not cascade into the main script or other libs. – BuvinJ Apr 18 '18 at 15:03
  • Unfortunately, that doesn't solve my problem. But at least it helps me to understand it. It will really suck if I'm just not able to use the protection because these third parties didn't respect it. – BuvinJ Apr 18 '18 at 15:06
  • Pretty sure your choices are as per my last comment - either run without `Option Explicit` in the main script (as that's enforcing it on the libraries you load and causing the runtime errors) or fix the other libraries issues... – Dave Apr 18 '18 at 15:08
  • 1
    Thanks, Dave. You're probably right. I'm just SOL. – BuvinJ Apr 18 '18 at 15:10
  • 1
    @Dave, check out the answer / discussion I had with Peter Cooper Jr. below. Most of what he said directly aligns with your posts. He managed to think up a useful nugget for confronting this though, which had eluded us. If you write vbs with third party libs, it's a useful design concept to keep in mind. – BuvinJ Apr 20 '18 at 00:56

1 Answers1

2

What's the rule about where Option Explicit must appear? Does it have to be the first line or not?

Per the documentation,

If used, the Option Explicit statement must appear in a script before any other statements.

Why is it kosher for it to not be the first line when I apply it via an "include"?

Well, as you said, it's not really "including", you just are loading text and evaluating a separate script at runtime with ExecuteGlobal. It's not substituting the text of the libraries within your script, it's loading and running a separate script. That separate script can have Option Explicit in it as the first statement, since it's run separately.

How can I achieve my objective?

In order to run with Option Explicit, you need to ensure all your libraries declare all their variables too. If you're not willing to find the variables names and modify the libraries to declare them, then I don't think you have any other alternatives.

You may be able to just have your main loading-scripts script not use Option Explicit, and anything more complex than that put in your own library that does use Option Explicit. Hopefully your main script is simple enough that it's easily debugged without using Option Explicit on it.

  • Thanks Peter. I like your final idea here. I could probably refactor the code so the main script is basically a light weight wrapper, and move all my meaningful work into a library. Then use OE on the new library. I'm wondering though, will everything work if the new lib has dependencies on the others? I mean if the main script "includes" the whole collection of them, the new lib could draw upon the others by virtue of having the parent script supply them to it? (even if the lib didn't work "standalone") – BuvinJ Apr 18 '18 at 20:23
  • @BuvinJ: I would expect so, given that ExecuteGlobal puts everything into the global namespace (and VBScript doesn't have a ton of "namespace" concepts anyway), but I haven't tried it myself. It should be easy enough to try it and check if it'd work for your purposes. –  Apr 18 '18 at 20:30
  • Well, a quick test revealed that this does not instantly solve the problem, but it's a step in the right direction. I moved everything in the main script into a "private" / "worker" script, other than the includes, and then made the last include the new worker script. I then added OE to the top of the new private script. That compiles, and draws upon the dependencies as we would hope, but I still get run time errors when calling into the sloppy libs from this new one. – BuvinJ Apr 18 '18 at 20:53
  • It took some effort, because the code is pretty extensive, and intertwined with these libraries, but I did in fact manage to get the majority of what I wrote into separate libs which apply OE, while keeping the third parties in a context without that restriction / protection. Thanks for the push in the right direction! – BuvinJ Apr 20 '18 at 00:49