Script Injection (and ExternalInterface in general) is not just limited to JavaScript. Using these same techniques, specialized Flash applications running under Internet Explorer (only) can take advantage of VBScript as well, leading us to debunk another common misconception:

False: In Browsers, ExternalInterface only works with JavaScript .

ExternalInterface actually works with any language that supports the NPRuntime API. And yes, for most browsers this means only JavaScript, since it's the universal browser language... However, if you're not programming for the general public, and can limit users to IE only, a whole new vista (Vista?) opens up: while not explicitly documented by Adobe, VBScript functions can also be set and called freely using ExternalInterface.

For instance, add the following VBScript to a webpage:

<script language="VBScript">
    Function myBox(txt)
        MsgBox(txt, 1)
    End Function
</script>

And it will be executed if you call ExternalInterface.call("myBox", "foo"). Niiiiiice!

As noted previously, VBScript access even works with the Script Injection techniques we just discussed, and yes, VBScript can be easily embedded into AS3 scripts using the XML technique! But there is a small problem. VBScript lacks the "Wrapper Function" ability of JavaScript, so there's no direct way to inject and execute complex scripts like we can with JavaScript.Lucky for us there's an indirect way, and we even get to fall back to JavaScript to pull it off.

Microsoft, with canny foresight, added a little-known (and poorly-documented) JavaScript command called execScript() which allows JavaScript (technically Jscript, Microsoft's version of the language) to take just about any language as a string and interpret it. It runs off the JavaScript window object:

window.execScript('MsgBox("foo", 1)', 'vbscript')

Handy, that! Too bad the online docs for it are so darned vague, or they might have mentioned that entire VBScript applications can be pumped into Internet Explorer through this little command. And that happens to be just what we need to do...

Injecting and Executing VBScript into a Webpage from Flash

That JavaScript -Inside-XML trick we learned earlier works for VBScript, too:

var myVBScript:XML =
    <vbscript>
        <![CDATA[
            Function myBox (txt)
                myBox = MsgBox(txt, 1)
            End Function
        ]]>
    </vbscript>

…but there's a problem. While VBScript does support Classes and Encapsulation, it doesn't support them in a way that allows us to create a Wrapper Function as we can for JavaScript . This makes script injection a little more complex, but as I mentioned earlier, IE has a special Jscript function called execScript() that fixes the problem.

The solution is to take the embedded VBScript, and convert it a string-based var that JavaScript can read, then run execScript() on the var. Carriage returns in VB are significant, so we need to maintain these when we write the JavaScript var out.

import flash.external.ExternalInterface;

function InjectVB(vbXML):* {
    var CRLF = String.fromCharCode(13)+String.fromCharCode(10);
    var vb = vbXML.toString();
    var vb_arr = vb.split(CRLF);
    var jsvb="function(){" + CRLF;
    jsvb += " var temp='';" + CRLF;
    for (var i = 0; i <vb_arr.length; i++) {
        var vbTemp = vb_arr[i];
        jsvb+=" temp+=('" + vbTemp + "' + String.fromCharCode(13));" + CRLF;
    }
    jsvb+= " window.execScript(temp, 'vbscript');" + CRLF;
    jsvb+= "}";
    trace(jsvb);
    ExternalInterface.call(jsvb);
}
InjectVB(myVBScript);<p>

What's happening? We take the XML from the previous example, and convert it to a string. We then convert it to an Array, splitting it on the carriage return - linefeeds that were in the XML (Mac users would be carriage returns only, but they can't use VBScript anyways). We then rewrite the array of strings into JavaScript commands. Once executed, the function above will generate our JavaScript function, which in turn will generate VBScript code once it hits the browser. Based on the example above, the JavaScript that would be written is:

function(){
    var temp='';
    temp+=(' Function myBox (txt)' + String.fromCharCode(13));
    temp+=('     myBox = MsgBox(txt, 2)' + String.fromCharCode(13));
    temp+=(' End Function ' + String.fromCharCode(13));
    window.execScript(temp, 'vbscript');
}

Which will, in turn, create the following VBScript function inside the webpage:

Function myBox (txt)
    myBox = MsgBox(txt, 1)
End Function

Note that execScript does not return a value, so it's necessary to use TWO ExternalInterface.call commands if you expect to get one… one call to inject the VBScript into the webpage using execScript, and one to actually call your function and get a value.

You can now call your myBox function using a normal ExternalInterface.call:

var holyCow = ExternalInterface.call("myBox", "Hey it works!");
// holyCow = 1: Clicked OK
// holyCow = 2: Clicked Cancel or Window Close Box

Complete working AS3 code for this example follows. Note that we also take advantage of a JavaScript alert() to relay the results once the MsgBox has been fired off:

import flash.external.ExternalInterface;
var myVBScript:XML =
    <vbscript>
        <![CDATA[
            Function myBox (txt)
                myBox = MsgBox(txt, 1)
            End Function
        ]]>
    </vbscript>
function InjectVB(vbXML):* {
    var CRLF = String.fromCharCode(13)+String.fromCharCode(10);
    var vb = vbXML.toString();
    var vb_arr = vb.split(CRLF);
    var jsvb="function(){" + CRLF;
    jsvb += " var temp='';" + CRLF;
    for (var i = 0; i <vb_arr.length; i++) {
        var vbTemp = vb_arr[i];
        jsvb+=" temp+=('" + vbTemp + "' + String.fromCharCode(13));" + CRLF;
    }
    jsvb+= " window.execScript(temp, 'vbscript');" + CRLF;
    jsvb+= "}";
    trace(jsvb);
    ExternalInterface.call(jsvb);
}
function alert(txt) {
    ExternalInterface.call("alert", txt);
}
function doIt(){
    InjectVB(myVBScript);
    var holyCow = ExternalInterface.call("myBox", "Hey it works!");
    // holyCow = 1: Clicked OK
    // holyCow = 2: Clicked Cancel or Window Close Box
    alert("You clicked: " + String(holyCow));
}
doIt();

Injection of VBScript isn't as useful as JavaScript, due to the fact that VBScript is only supported on IE. But so long as you know your users are only browsing with Internet Explorer on Windows, your Flash application will now have near-complete control over VBScript, allowing you to directly manage ActiveX controls, utilize the very useful MsgBox procedure, and do other things that VB offers which JavaScript and Flash alone do not.