【问题标题】:ScriptControl.AddCode without executing the code?ScriptControl.AddCode 不执行代码?
【发布时间】:2015-01-15 07:27:10
【问题描述】:

我正在开发一个 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 中,就会执行 ma​​in 子程序,我会看到消息框出现。

有人知道在这种情况下避免执行 ma​​in 子的简单方法吗?

我当前的解决方法(目前仅针对 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;
}

欢迎任何更好的想法。

【问题讨论】:

    标签: javascript c# vbscript jscript enterprise-architect


    【解决方案1】:
    1. 如果您希望脚本代码模块在没有任何静态初始化程序的情况下充当代码库,那么您可以通过在编码约定

    2. 中声明它来强制执行它
    3. 如果您希望静态初始化程序和其他副作用在运行时才出现,那么您可以通过 延迟加载 脚本在需要时推迟脚本激活第一次

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

      MSDN: Windows Script Interfaces

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

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

    【讨论】:

    • 1.我无法控制脚本,因此无法强制执行任何编码约定。 2. 我马上需要脚本,所以不能延迟加载,并且在任何情况下都不应该执行main这样的语句。 3. 恐怕这将是我最后的选择,但这需要认真的返工。我仍然希望有人想出奇迹般的解决方案。
    • 虽然这不是我希望找到的答案,但我不得不接受这个。有时答案是“不,这做不到”。最后我停止尝试修改脚本,而是只选择了我知道要为我的加载项编写的那些脚本,因为它们包含关键字“EA-Matic”
    【解决方案2】:

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

    【讨论】:

    • @Serentity 我知道这一点。这就是为什么我在将代码添加到 ScriptControl 之前将其剥离的原因。我正在寻找一种避免执行代码的方法。
    • AddCode 必须执行顶级命令。环境就是这样设置的。 Script Control 正在做正确的事情。
    猜你喜欢
    • 2015-12-19
    • 2018-09-29
    • 2018-02-23
    • 2013-06-06
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多