Adventures in VBScript – Including code from other files
If you’re a VBScript hack like me, you’re probably frustrated by the inability of VBScript to include code from other files natively. Yes, you can use funky Job files etc, but nothing beats the simplicity of an all-in-one .VBS.
I’ve created innumerable “helper” scripts and classes over the years, and even wrote a tool I call “region” which selectively merges different files together to make one big (unreadable) script.
My utopia of having simple, small scripts which leveraged my 20 year programming library has not been achieved, until now.
Here you’ll find my “Include for VBS” function – surprisingly simple, but it took 20 years of thinking about it before I got around to writing it. There were two problems to solve:
1. How to read code from another file and have it available to the script
That’s the easy part – VBScript easily reads text files, and the executeglobal statement allows you to “add” code to the runtime in memory.
2. Don’t include things twice, or three times etc
Harder – as it requires the include function to track what modules it’s loaded. Since the Include function might be in a class, we need to make sure we don’t include things multiple times for multiple classes etc – it’s all to do with scope.
Thankfully the executeglobal and eval functions come to our aid again – we can use them to create variables on the fly in the global workspace which we can use to track which files we’ve loaded.
So, with those problems solved – here’s my snippit to reliably include files ONCE in your VBScripts, saving you duplicating the same code over and over again.
Sub Include(fSpec) ' Sub to load file modules (Once!) ' Simply call this function with the path to the vbs file you want to include, and it will be ' loaded into memory ONCE, even if you try to load it a number of times. Dim sTemp On Error Resume Next sTemp = Eval("ICLF") On Error Goto 0 If IsEmpty(sTemp) Then ' no currently loaded files - first Include run ExecuteGlobal "Dim ICLF : ICLF = 0" End If ' test to see if file has already been loaded If InStr(1,iclf,fspec,vbTextCompare)=0 Then With CreateObject("Scripting.FileSystemObject") If .fileexists(fspec) Then ExecuteGlobal .openTextFile(fSpec).readAll() Else MsgBox "Include file " & fspec & " not found. Exiting",vbOKOnly+vbExclamation,"Critical Error." WScript.Quit End If End With ICLF = ICLF & "|" & fspec Else ' file already loaded End If End Sub
Why would you still use Vbsript in modern day and age where PowerShell v5 is about to be released which has this functionality built in (in addition to others).
Because I like VBS more than powershell? Because I have a huge legacy of very reliable, robust helper classes, and because I’m not automating sysadmin tasks, I’m writing programs.
Pretty much every language other than VBS has an include function – it doesn’t mean they are better for a particular job (or person).
I have written VBS (WSH) scripts since Windows 2000 as well. I just don’t get trying to work around limitation of something which was last updated in 2009 (last update to WSH) when PowerShell is available. I’ll not be surprised they will pull support for VBscript in next version of Windows or something. It’s probably feels like trying to optimize batch files while WSH was already available for scripting needs. It has it’s purpose but it’s worth investing in moving to something new instead.
How do you “write programs” with Vbscript anyway? It’s interpreted language, so what kinds of programs do you write?
I think a theological discussion on the benefits of various languages it outside the scope of this topic.
I too have used vbscript over many years and have a significant library of reusable components. The lack of an include was frustrating and I solved the problem the same way you have. The most significant problem with the approach is tracing errors when they occur. Because the entire script source does not exist in a single file, errors that occur reference line numbers that cannot be easily translated to the actual source line. Other than that it works well and has saved me tons of time assembling solutions from my library of script source class modules.
To the other point, admittedly vbscript is not a full featured developer tool and suffers from significant limitations especially on the UI front…however…outside of automating operational admin tasks vbscript can walk all over PowerShell. I see vbscript has a dumbed down flavour of MS VBA/Visual Basic with one hand tied behind its back. The power comes from the ease of use as an interpreted tool and the ability to instantiate class library methods using “CreateObject”. All of these tools have their strengths/weaknesses and if you actually use them you will understand when to pick what for a particular task. In an MS environment, between Visual Studio, VBScript, Powershell and ASP/ASP.Net there is very little you can’t accomplish from admin automation, to full blown classic client and web apps.
Thanks for your comments Dave – I agree for speed of implementation, VBScript is hard to beat. Re debugging though, I can recommend the excellent VBSEdit – it handles included modules admirably!