CodeFluent与Interop.MSScriptControl.dll

我们有一个32位服务,我们正试图迁移到64位。

我们使用Interop.MSScriptControl.dll来评估用户编写的vb脚本。

由于没有64位版本的MSScriptControl 。 我创建了一个在服务中调用的进程。 每次我们需要评估用户脚本时,我们都会调用该过程。 尝试此解决方案后,我发现它确实很慢。

我刚刚发现了CodeFluentRuntimeClient库,它可以评估vb脚本和JavaScript。 但是,它评估脚本的方式与MSScriptControl库完全不同。

我创建了一个简单的测试程序来评估用户编写的旧vb脚本。

 public class VBScriptEvaluator { public static dynamic Evaluate(string key, string script, IDictionary parameterValuePair) { try { using (ScriptEngine engine = new ScriptEngine(ScriptEngine.VBScriptLanguage)) { ParsedScript parsed = engine.Parse(string.Format(@"Function {0}() {1} End Function", key, script)); if (script.Contains("NecUserProfile")) engine.SetNamedItem("NecUserProfile", @"" + "ADMIN" + @""); //Hardcoded For now if (parameterValuePair != null && parameterValuePair.Count > 0) { foreach (var para in parameterValuePair) engine.SetNamedItem(para.Key, para.Value); } dynamic value = parsed.CallMethod(key); return (value != null) ? value.ToString() : string.Empty; } } catch (Exception ex) { throw; } } } 

如果我这样使用,它的工作正常:

 static void Main(string[] args) { string key = "necGlobalValue"; string script = @"necGlobalValue = ""ADMIN"""; var result = VBScriptEvaluator.Evaluate(key, script, null); //ADMIN } 

像这样它也很好用:

 static void Main(string[] args) { Dictionary parameterValuePair = new Dictionary(); parameterValuePair.Add("ZINVOICE_MARGIN_0", 141615427.8); parameterValuePair.Add("ZINVOICE_AMTNOTLIN_0", 187260276.84); var script = @"If (ZINVOICE_AMTNOTLIN_0)  0 Then SERVER_FLD0000001 = Abs(ZINVOICE_MARGIN_0) / ZINVOICE_AMTNOTLIN_0 else SERVER_FLD0000001 = 0 End If"; var key = "SERVER_FLD0000001"; var result = VBScriptEvaluator.Evaluate(key, script, parameterValuePair); } 

在之前的库中,它自动检测将要评估的变量的类型。 我可以将整数作为字符串传递,它会正常工作。

如果我像使用ScripEngine一样替换字典的值,它将失败:

 Dictionary parameterValuePair = new Dictionary(); parameterValuePair.Add("ZINVOICE_MARGIN_0", "141615427.8"); parameterValuePair.Add("ZINVOICE_AMTNOTLIN_0", "187260276.84"); 

此外,如果我这样做,我没有得到用户ADMIN。

 string key = "necGlobalValue"; string script = @"necGlobalValue = ""NecUserProfile"""; var result = VBScriptEvaluator.Evaluate(key, script, null); // output NecUserProfile instead of ADMIN 

而BTW我试图提供尽可能多的细节,这就是为什么这个问题很长的原因。

我通过将参数传递给函数而不是使用SetNamedItem函数SetNamedItem工作。

 public class VBScriptEvaluator { public static dynamic Evaluate(string key, string script, IDictionary parameterValuePair = null) { try { using (ScriptEngine engine = new ScriptEngine(ScriptEngine.VBScriptLanguage)) { List parameters = new List() { "ADMIN" }; string extraParameters = string.Empty; if (parameterValuePair != null && parameterValuePair.Count > 0) { extraParameters = "," + string.Join(",", parameterValuePair.Select(e => e.Key)); foreach (var para in parameterValuePair) parameters.Add(para.Value); } string parsedScript = string.Format(@"Function {0}(NecUserProfile {2}) {1} End Function", key, script, extraParameters); ParsedScript parsed = engine.Parse(parsedScript); dynamic value = parsed.CallMethod(key, parameters.ToArray()); return (value != null) ? value.ToString() : string.Empty; } } catch (Exception ex) { throw; } } } 

以下是如何使用它:

 Dictionary parameterValuePair = new Dictionary() { {"Param1", 100.0 }, {"Param2", 10.0} }; var script = @"If (Param2) <> 0 Then result = Param1 + Param2 else result = 1 + 2 End If"; var key = "result"; var result = VBScriptEvaluator.Evaluate(key, script, parameterValuePair); // output 110