ScriptControl.AddCode 而不执行代码

ScriptControl.AddCode without executing the code?

本文关键字:执行 代码 AddCode ScriptControl      更新时间:2023-09-26

我正在用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 将此脚本的代码添加到脚本控件中,就会执行子,并看到消息框出现。

有谁知道在这种情况下避免执行子的简单方法?

我目前的解决方法(目前仅适用于 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. 如果希望脚本代码模块充当没有任何静态初始值设定项的代码库,则可以通过在编码约定中声明它来强制执行它

  2. 如果希望静态初始值设定项和其他副作用在运行时之前不显示,则可以通过在第一次需要脚本时延迟加载脚本来推迟脚本激活

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

    MSDN:Windows 脚本接口

    。为了使主机的实现尽可能灵活,提供了适用于 Windows 脚本的 OLE 自动化包装器。但是,使用此包装器对象实例化脚本引擎的主机对运行时命名空间、持久性模型等的控制程度不如直接使用 Windows 脚本时那样。

    Windows 脚本设计隔离了仅在创作环境中所需的界面元素,以便非创作主机(如浏览器和查看器)和脚本引擎(例如 VBScript)可以保持轻量级...

Main 执行,因为您从顶级命令调用它。任何不在子/函数中的东西都会被执行。