Call a function written on VB from a JScript code (classic ASP)

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-01 04:36:35

I've been monitoring this question for a while and Salman has pretty much answered it but there are some things that could be clarified. First of all there is key problem with the article being referenced. It says that the order of execution is this:-

1.Script in elements in nondefault languages
2.Inline script
3.Script in elements in the default language

Its wrong, or at least its out of date (it does after all reference IIS4). The "inline script" (that is script in the default language) is not treated any differently than script elements of the same language.

Here is how to reason through what is happening.

  • Before any parsing begins all the include points are resolved and replaced by content from the include files to create a single lexical "file". This is created before any parsing takes place.

  • Script code is collected from this "file" for each language. You can imagine multiple files (one per language) being appended to as each chunk is found. Note that this is the reason why <% %> and <script runat="server" for the default language are practically indistiguishable.

  • Any static content (that is content outside of a runat="server" script tag or <% %>) is considered to be part of the code for the default language. A special form of Response.Write that sends the static content bytes verbatim to the response is created and appended to the default language code at the point it was found in the original file.

  • Now we have one or more scripts that are ready to be processed by their respective script engines. The non-default language scripts are parsed and executed first. Any global identifier created, be that for a function or a variable, is added to the script environment. However since the default language script has not been processed at all at this point nothing that it might subsequently add to the global script environment is yet available.

  • By the time the default language script is parsed and executed all the global identifiers created by the previous language scripts will have been added to the script environment and are therefore available for use from inline code.

You should note carefully that a default language function can be called by code in a function in the non-default language on the condition that call into the non default function can be traced back to the inline execution of the default language.

For example if the default language is JScript you can have a VBScript function (fnA) call a function declared in JScript (fnB) as long as the call to fnA is made as part of the inline execution of JScript. IOW JScript can call into VBScript which in turn can call into VBScript and so on, the limiting factor is the engine that the top of this chain must be JScript in this scenario.

In your example code you had code at the global (inline) level of your VBScript attempting to call a function declared in the default JScript language. If you follow the above bullets you will see that at the point it is executed the the function being called does not exist.

I encourage you not to mix scripting languages. In the article you mentioned, there is a heading titled "Server Script Order of Execution" where it says:

... However, you are then at the mercy of the order of execution of the IIS ASP processor. For example, if you create server script and run it in IIS 4.0, you'll find this execution order:

  1. Script in <SCRIPT> elements in nondefault languages
  2. Inline script
  3. Script in <SCRIPT> elements in the default language

Keeping that in mind, here is how your testjs.asp script is executed, comments indicate execution order:

<%@ Language="JavaScript" %>
<script language="vbscript" runat="server">
    '' #1
    Sub VBTestFunction(Message)
        Response.Write "VBTestFunction: " & Message
    End Sub
</script>
<script language="javascript" runat="server">
    // #3
    function JSTestFunction(Message) {
        Response.Write("JSTestFunction: " + Message);
    }
</script>
<script language="javascript" runat="server">
    // #4
    VBTestFunction("from javascript");
    JSTestFunction("from javascript");
</script>
<script language="vbscript" runat="server">
    '' #2
    Call VBTestFunction("from vbscript")
    Call JSTestFunction("from vbscript")
</script>

Notice the line that causes error:

Call JSTestFunction("from vbscript")

Its execution order is #2; at this point the function JSTestFunction is not defined (it is defined later in the execution order).

Now for testvbs.asp file:

<%@ Language="VBScript" %>
<script language="vbscript" runat="server">
    '' 3
    Sub VBTestFunction(Message)
        Response.Write "VBTestFunction: " & Message
    End Sub
</script>
<script language="javascript" runat="server">
    // 1 
    function JSTestFunction(Message) {
        Response.Write("JSTestFunction: " + Message);
    }
</script>
<script language="javascript" runat="server">
    // 2
    VBTestFunction("from javascript");
    JSTestFunction("from javascript");
</script>
<script language="vbscript" runat="server">
    '' 4
    Call VBTestFunction("from vbscript")
    Call JSTestFunction("from vbscript")
</script>

The line that causes error:

VBTestFunction("from javascript");

Again, VBTestFunction is called before it is defined. The solution is to try not to mix scripting languages. If it is absolutely necessary, revise the order of your scripts.

Edit -- Example

If you have set @ Language="JavaScript" then this code should work as expected:

<!-- inc.asp-->
<script language="vbscript" runat="server">
    Sub VBTestFunction(Message)
        Response.Write "VBTestFunction: " & Message
    End Sub
</script>
<%
    function JSTestFunction(Message) {
        Response.Write("JSTestFunction: " + Message);
    }
%>

<!-- testjs.asp -->
<%@ Language="JavaScript" %>
<!-- #include file="inc.asp"-->
<%
    // at this point, both functions are available
    VBTestFunction("from inline JavaScript");
    JSTestFunction("from inline JavaScript");
%>

If you want to use @ Language="VBScript" then you have to re-arrange all code:

<!-- inc.asp-->
<script language="javascript" runat="server">
    function JSTestFunction(Message) {
        Response.Write("JSTestFunction: " + Message);
    }
</script>
<%
    Sub VBTestFunction(Message)
        Response.Write "VBTestFunction: " & Message
    End Sub
%>

<!-- testvbs.asp -->
<%@ Language="VBScript" %>
<!-- #include file="inc.asp"-->
<%
    ' at this point, both functions are available
    VBTestFunction("from inline VBScript")
    JSTestFunction("from inline VBScript")
%>
Cheeso

I don't know all the rules, but this works for me:

test.asp:

<%@ language="JavaScript" %>

<script language="VBScript" runat="server" src="mix2.vbs"></script>

<script language="JavaScript" runat="server">
    TestFunction("from javascript");
</script>

mix2.vbs:

Sub TestFunction (message)
    Response.Write message
End Sub

Notice:

  • there is no <script> tag in the vbs file that gets included.
  • the <%@ language="..." %> tag at the top, should indicate the "primary" language. The <script> blocks that use the secondary language (in your case, VBScript) will then be interpreted and available for any code in the primary language.

Maybe related: How can I use Javascript OO classes from VBScript, in an ASP-Classic or WSH environment?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!