Integrating new libraries for use in OpenInsight is often facilitated by taking an existing VBScript code library and calling it from OpenInsight using the MSScriptControl.ScriptControl COM object. This enables OpenInsight to interact with the VBScript code as if it were a COM library. It's a powerful technique when it's too complicated to translate a VB or VBScript example into BASIC+ code or when dealing with COM library that returns data objects that OpenInsight can't support.
Techniques for embedding VBScript code in BASIC+ code vary but they all follow this pattern:
- Write a wrapper in the VBScript language that interacts with the desired library.
- Create a MSScriptControl.ScriptControl COM object using OLECreateInstance().
- Load the VBScript code wrapper into the COM object from either a literal string or saved record.
- Use the OpenInsight OleCallMethod function or "->" operator to call the VBScript wrapper functions.
This article focuses on two methods for interacting with the VBScript code, using the Run or Eval methods. If you've dealt with this technique before you may have used one or both methods. While Eval has a very different purpose and can run code on-the-fly they both appear interchangable for calling methods but upon further examination there is an important difference you must be aware of that we'll cover at the end of the article.
Here is a sample script saved as a literal string and BASIC+ code that calls the VBScript wrapper using Run and Eval:
Subroutine CS_VBSCRIPT_EVALRUN_EXAMPLE(void) sc = '' sc<-1> = 'Dim varGlobal' sc<-1> = 'Function getGlobal()' sc<-1> = 'getGlobal = varGlobal' sc<-1> = 'End Function' sc<-1> = 'Sub setGlobalSub(valNew)' sc<-1> = 'varGlobal = valNew' sc<-1> = 'End Sub' sc<-1> = 'Function setGlobalFunc(valNew)' sc<-1> = 'varGlobal = valNew' sc<-1> = 'End Function' *Create an OLE script control to execute the VBScript code objWrapper = OLECreateInstance("MSScriptControl.ScriptControl") objWrapper->Language = "VBScript" *Format the code example with CRLF and add it to the script control. Swap @FM With \0D0A\ In sc void = objWrapper->AddCode( sc ) OIVal = "Set from OI using Run Func" void = objWrapper->Run('setGlobalFunc', OIVal) RetVal = objWrapper->Run('getGlobal') If RetVal NE OIVal Then Debug OIVal = "Set from OI using Run Sub" void = objWrapper->Run('setGlobalSub', OIVal) RetVal = objWrapper->Run('getGlobal') If RetVal NE OIVal Then Debug OIVal = 'Set From OI using Eval Func' void = objWrapper->Eval('setGlobalFunc("' : OIVal :'")') RetVal = objWrapper->Run('getGlobal') If RetVal NE OIVal Then Debug OIVal = 'Set From OI using Eval Sub' RetVal = objWrapper->Eval('setGlobalFunc("' : OIVal :'")') valEvalFunc = objWrapper->Eval('getGlobal()') If RetVal NE OIVal Then *This is expected because Eval cannot call Sub routines in the script library. *See http://support.microsoft.com/kb/184740 Call Msg("Cannot call a Sub using Eval()") End
The VBScript code has two functions:
Functions are expected to return a value but can return nothing.
The VBScript code also has one subroutine:
Subroutines do not return a value.
The script example above is a simple demonstration of setting and getting a variable from within the VBScript library. The purpose of this example is to show that while Eval and Run often work interchangeably it is not possible to use Eval to call a VBScript method declared as a Sub. This is confirmed in the Microsoft Support article How To Call Functions Using the Script Control which states:
This [Eval] method cannot be used to call Subroutines.
If you haven't worked with embedding VBScript code and are looking for some more examples of why this is a powerful technique to master here are a few more examples worth checking out: