2016-09-23 59 views
2

我們有一個32位的服務,我們試圖遷移到64位。CodeFluent vs Interop.MSScriptControl.dll

我們使用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 

而且BTW我試着給儘可能多的細節,這就是爲什麼這個問題是那麼長。

+1

雖然ScriptEngine的是基於相同的(舊)基本技術爲MSScriptControl(「ActiveX腳本」),他們可能會在某些方面有所不同。但是,它不應該是這樣的問題。在你的例子中,ScriptEngine按預期工作。但是命名項通常用於複雜的對象(如HTML中的'document'或ASP中的'Request'),而不是像字符串或整數這樣的整體對象。如果要傳遞標準參數,請在函數中聲明它們,並使用CallMethod傳遞它們。另外,出於性能原因,您希望保留解析對象,而不是在每次調用時分析。 –

+0

這就是我最後所做的,它的工作很好(使用參數代替'SetNamedItem')。我只是沒有時間回答我自己的問題。順便說一句,我想感謝你的圖書館,這真棒。 – billybob

+0

是否將MSScriptControl放入32位dllhost.exe允許它在沒有任何附加代碼的情況下工作?理論上它應該。 – 2016-09-27 00:23:59

回答

1

我通過將參數傳遞給函數而不是使用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 
相關問題