ScriptControl.AddCode 不执行代码?

ScriptControl.AddCode without executing the code?

我正在使用 C# 开发一个项目,该项目从 EA 数据库获取脚本(VBScript、Jscript 和 JavaScript)并在特定时刻执行某些功能。

为了能够做到这一点,我使用 Microsoft ScriptControl

首先,我使用 ScriptControl.AddCode 将所有脚本代码添加到 ScriptControl,然后我使用特定名称运行。

将代码添加到脚本控件的代码如下所示:

//create new scriptcontroller
this.scriptController = new ScriptControl();
this.scriptController.Language = this.language.name;
this.scriptController.AddObject("Repository", model.getWrappedModel());
//Add the actual code. This must be done in a try/catch because a syntax error in the script will result in an exception from AddCode
try
{
    //first add the included code
    string includedCode = this.IncludeScripts(this._code);
    //then remove any statements that execute a function or procedure because scriptControl.AddCode actually executes those statements
    string cleanedCode = this.language.removeExecutingStatements(includedCode);
    //then add the cleaned code to the scriptcontroller
    this.scriptController.AddCode(cleanedCode);

问题是显然 AddCode 也以某种方式执行脚本代码,这不是我想要的。

假设我有以下 VBScript:

sub main
    MsgBox("main executed")
end sub

main

只要我使用 AddCode 将此脚本的代码添加到 ScriptControl,就会执行 main 子程序,我会看到消息框出现。

有人知道在这种情况下避免执行 main sub 的简单方法吗?

我当前的解决方法(目前仅针对 VBScript 实现)涉及解析脚本代码并删除调用函数或过程的行,但这非常乏味且容易出错。

/// <summary>
/// removes the statements that execute a function/procedure from the code
/// </summary>
/// <param name="code">the code with executing statements</param>
/// <returns>the code without executing statements</returns>
public override string removeExecutingStatements(string code)
{
    StringReader reader = new StringReader(code);
    string cleanedCode = code;
    string line;
    bool functionStarted = false;
    bool subStarted = false;
    while (null != (line = reader.ReadLine()))
    { 

        if (line != string.Empty)
        {
            if (line.StartsWith(this.functionStart))
            {
                functionStarted = true;
            }else if (line.StartsWith(this.subStart))
            {
                subStarted = true;
            }else if (functionStarted && line.StartsWith(this.functionEnd))
            {
                functionStarted = false;
            }
            else if (subStarted && line.StartsWith(this.subEnd))
            {
                subStarted = false;
            }else if (!functionStarted && !subStarted)
            {
                //code outside of a function or sub, figure out if this code calls another sub or function
                foreach (string linepart in line.Split(new char[] {' ' , '(' },StringSplitOptions.RemoveEmptyEntries))
                {
                    if (cleanedCode.Contains(this.functionStart + linepart)
                        ||cleanedCode.Contains(this.subStart + linepart))
                    {
                        //found a line that calls an existing function or sub, replace it by an empty string.
                        cleanedCode = cleanedCode.Replace(Environment.NewLine +line + Environment.NewLine, 
                                                          Environment.NewLine + string.Empty + Environment.NewLine);
                    }
                }
            }
        }
    }
    return cleanedCode;
}

欢迎提出更好的意见。

  1. 如果您希望脚本代码模块充当没有任何静态初始值设定项的代码库,那么您可以通过在编码约定[=12 中声明它来强制执行它=]

  2. 如果您希望静态初始化程序和其他副作用在 运行 之前不出现,那么您可以通过 延迟加载 第一次需要时的脚本

  3. 如果您想对脚本环境进行更细粒度的控制,您可以实施脚本主机并更直接地与脚本引擎交互(例如,使用 IActiveScriptParse 接口可能不会触发任何意外的副作用)。

    MSDN: Windows Script Interfaces

    ...To make implementation of the host as flexible as possible, an OLE Automation wrapper for Windows Script is provided. However, a host that uses this wrapper object to instantiate the scripting engine does not have the degree of control over the run-time name space, the persistence model, and so on, that it would if it used Windows Script directly.

    The Windows Script design isolates the interface elements required only in an authoring environment so that nonauthoring hosts (such as browsers and viewers) and script engines (for example, VBScript) can be kept lightweight...

Main 执行是因为您从顶级命令调用它。不在 sub/functions 中的任何内容都会被执行。