我正在使用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 子,我会看到消息框出现。
有没有人知道在这种情况下避免执行主子的简单方法?
我当前的解决方法(目前仅针对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;
}
欢迎任何更好的主意。
答案 0 :(得分:1)
如果您希望脚本代码模块在没有任何静态初始值设定项的情况下充当代码库,那么您可以通过在编码约定
如果您希望静态初始值设定项和其他副作用在运行时才显示,那么您可以通过延迟加载脚本来推迟脚本激活。第一次
如果您希望对脚本环境进行更细粒度的控制,那么实现脚本主机并更直接地与脚本引擎交互(例如使用{{1} } interface可能不会触发任何意外的副作用。)
MSDN: Windows Script Interfaces
...为了使主机的实现尽可能灵活,提供了一个用于Windows脚本的OLE自动化包装器。但是,使用此包装器对象实例化脚本引擎的主机不具有对运行时名称空间,持久性模型等的控制程度,如果它直接使用Windows脚本,则无法控制。
Windows脚本设计隔离了仅在创作环境中所需的界面元素,以便非授权主机(例如浏览器和查看器)和脚本引擎(例如,VBScript)可以保持轻量级...
答案 1 :(得分:0)
Main执行是因为您从顶级命令调用它。执行不在子/函数中的任何内容。