Вопрос

Итак, я использую 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 box, и выдает мне номер строки с ошибкой.Поэтому я с радостью публикую и отправляю его на производственную машину, которая всегда сообщает мне, что произошла ошибка в строке 0, и описание не приводится.

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

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

Это было полезно?

Решение

относительно проблемы, с которой вы сталкиваетесь с некоторыми мыслями:

    .
  • Согласно ссылке, которую вы предоставили, этот элемент управления не поддерживает Windows 7, ни Windows 2008
  • Это может быть проблема безопасности в отношении com / uac etc.
  • Это может быть проблемой из-за укуты, если вы собирались для AnyCPU, попробуйте использовать x86

Что касается возможных альтернатив:

    .
  • Использование jscript Вы можете построить http Оценщик довольно легко который поддерживается где угодно .NET 4 (включая WindowsСервер 2008).
  • Использование jint в качестве интерпретатора JavaScript

Другие советы

Если вы хотите сделать это на всем родном 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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top