Проблема MSScriptControl в Windows Server 2008 - PullRequest
0 голосов
/ 15 марта 2012

Итак, я использую MSScriptControl для запуска некоторого javascript в своем приложении и хочу получить информацию о любых ошибках, которые может вызвать скрипт.

MSScriptControl.ScriptControlClass script = new MSScriptControl.ScriptControlClass();
try
{
    script.Language = "JScript";
    script.Timeout = 15000;
    script.Eval(Code);
}
catch (Exception ex)
{
    MSScriptControl.Error err = script.Error;
    ret = new Exception("Error on line: " + err.Line + ", Description: " + err.Description);
}

Код отлично работает на моей машине для разработки под управлением Windows 7 и выдает номер строки с ошибкой. Поэтому я с радостью публикую и отправляю его на рабочий компьютер, который всегда сообщает мне, что произошла ошибка в строке 0, и описание не предоставляется.

Я пытался зайти на http://www.microsoft.com/download/en/details.aspx?id=1949, чтобы загрузить последнюю версию, но установка не дала результата. Я также установил для свойства Embed Interop Types значение false, а также скопировал свой собственный файл msscript.ocx в каталог system32 на сервере Windows 2008, но ни одна из этих попыток ничего не дала.

У кого-нибудь есть рекомендации?

Ответы [ 2 ]

2 голосов
/ 20 марта 2012

Если вы хотите сделать это во всех нативных c # без каких-либо сторонних или «компонентных» внешних зависимостей, используйте CodeDomProvider с крошечной начальной загрузкой JScript, например:

private static readonly MethodInfo eval = CodeDomProvider
        .CreateProvider("JScript")
        .CompileAssemblyFromSource(new CompilerParameters(), "package e{class v{public static function e(e:String):Object{return eval(e);}}}")
        .CompiledAssembly
        .GetType("e.v")
        .GetMethod("e");

private static object JsEval(string jscript)
{
    try
    {
        return eval.Invoke(null, new[] { jscript });
    }
    catch (Exception ex)
    {
        return ex;
    }
}

, которая создает JsEval(string) метод, который вы можете использовать в любом месте своего кода, чтобы «оценить» строку как JavaScript (ну, в общем, JScript) ... Итак, вызов:

MessageBox.Show("" + JsEval("2 + 2")); // 4
MessageBox.Show("" + JsEval("(function(){ return 3+7; })();")); // 10
MessageBox.Show("" + JsEval("function yay(a) { return a + 1; } yay(2);")); // 3

, в зависимости от вашего использования, вы можете не захотеть создавать экземпляры этих членовстатически.если вы хотите манипулировать сложными объектами, вам потребуется создать обертку для рефлексивного извлечения данных (или вы можете привести их в качестве соответствующего аналога JScript, но я никогда не пробовал этого, так как вам нужно было бы включать сборки JScript).

здесь приведен пример класса-обертки, который делает все, что JavaScript позволит вам делать изначально, добавление более высокоуровневой функциональности, вероятно, будет достаточно громоздким, так что вам будет лучше либо извлечь элементы в словарь /хеш-таблицу ИЛИ альтернативно сериализацию и десериализацию на другом конце

private class JsObjectWrapper : IEnumerable
{
    public readonly object jsObject;
    private static PropertyInfo itemAccessor = null;
    private static MethodInfo getEnumerator = null;

    public JsObjectWrapper(object jsObject)
    {
        this.jsObject = jsObject;

        if (itemAccessor == null) 
        {
            itemAccessor = jsObject.GetType().GetProperty("Item", new Type[] { typeof(string) });
        }

        if (getEnumerator == null)
        {
            getEnumerator = jsObject.GetType().GetInterface("IEnumerable").GetMethod("GetEnumerator");
        }
    }

    public object this[string key]
    {
        get { return itemAccessor.GetValue(jsObject, new object[] { key }); }
        set { itemAccessor.SetValue(jsObject, value, new object[] { key }); } 
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return (IEnumerator)getEnumerator.Invoke(jsObject, null);
    }
}

вы можете увидеть это в действии, выполнив следующее:

var jsObj = JsEval("var x = { a:7, b:9 };");
var csObj = new JsObjectWrapper(jsObj);

MessageBox.Show("a: " + csObj["a"]);  // a: 7
MessageBox.Show("b: " + csObj["b"]);  // b: 9

csObj["yay!"] = 69;

foreach (string key in csObj)
{
    MessageBox.Show("" + key + ": " + csObj[key]); // "key": "value"
}

лично я использовал код, похожий на этот, для большого эффектав тот или иной момент он может поручиться за его доступность и работоспособность в серверной среде. Надеюсь, это поможет -ck

1 голос
/ 20 марта 2012

Относительно проблемы вы столкнулись с некоторыми соображениями:

  • по предоставленной вами ссылке, этот элемент управления не поддерживает ни Windows 7, ни Windows 2008
  • , это может быть проблема безопасности в отношениив COM / UAC и т. д.
  • это может быть проблемой из-за разрядности, если вы скомпилировали для AnyCPU, попробуйте использовать x86

В отношении возможных альтернатив:

  • Используя JScript , вы довольно легко можете создать оценщик , который поддерживается везде, где работает .NET 4 (включая Windows Server 2008).
  • Использование JInt как интерпретатор JavaScript
...