2016-09-23 7 views
2

64ビットに移行しようとしている32ビットサービスがありました。CodeFluentとInterop.MSScriptControl.dll

ユーザーが作成したVBスクリプトを評価するのにInterop.MSScriptControl.dllを使用しています。

MSScriptControlの64ビットバージョンがないため、私はサービス内で呼び出されたプロセスを作成しました。ユーザースクリプトを評価する必要があるたびに、プロセスを呼び出します。この解決策を試した後、私はそれが本当に遅いと感じました。

私はちょうど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 

私は多くの詳細を与えようとしましたが、その理由はそれほど長いことです。

+1

たScriptEngineがMSScriptControl(「ActiveXのスクリプティング」)と同じ(旧)基本的な技術に基づいているが、彼らはいくつかの点で異なる場合があります。しかし、それはそのような問題であってはならない。あなたの例では、ScriptEngineは期待通りに動作します。しかし、名前付きアイテムは一般に複雑なオブジェクト(HTMLの 'document'やASPの 'Request'など)に使用され、文字列や整数などの整数オブジェクトでは使用されません。標準パラメータを渡したい場合は、関数で宣言し、CallMethodで渡します。また、パフォーマンス上の理由から、各呼び出し時に解析するのではなく、解析されたオブジェクトを保持する必要があります。 –

+0

これは私が最後にやったことです。うまく動いています( 'SetNamedItem'ではなくパラメータを使用しています)。私は自分の質問に答える時間がなかっただけです。そしてbtw、私は図書館に感謝したい、それは素晴らしいです。 – billybob

+0

MSScriptControlを32ビットdllhost.exeに入れると、追加コードなしで動作するのですか?理論的にはそれはすべきです。 –

答えて

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 
関連する問題