![](/img/trans.png)
[英]CodeFluent.RunTime.Client.dll - AccessViolationException
[英]CodeFluent vs Interop.MSScriptControl.dll
我們有一個 32 位服務,我們正嘗試將其遷移到 64 位。
我們使用Interop.MSScriptControl.dll
來評估用戶編寫的 vb 腳本。
由於沒有 64 位版本的MSScriptControl
。 我創建了一個在服務內部調用的進程。 每次我們需要評估用戶腳本時,我們都會調用該過程。 嘗試了這個解決方案后,我發現它真的很慢。
我剛剛發現了可以評估 vb 腳本和 JavaScript 的CodeFluentRuntimeClient
庫。 但是,它評估腳本的方式與MSScriptControl
庫完全不同。
我創建了一個簡單的測試程序來評估用戶編寫的舊 vb 腳本。
public class VBScriptEvaluator
{
public static dynamic Evaluate(string key, string script, IDictionary<string, object> 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<string, object> parameterValuePair = new Dictionary<string, object>();
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<string, object> parameterValuePair = new Dictionary<string, object>();
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
順便說一句,我試圖提供盡可能多的細節,這就是問題那么長的原因。
我通過將參數傳遞給函數而不是使用SetNamedItem
函數來SetNamedItem
工作。
public class VBScriptEvaluator
{
public static dynamic Evaluate(string key, string script, IDictionary<string, object> parameterValuePair = null)
{
try
{
using (ScriptEngine engine = new ScriptEngine(ScriptEngine.VBScriptLanguage))
{
List<object> parameters = new List<object>() { "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<string, object> parameterValuePair = new Dictionary<string, object>()
{
{"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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.