Подтвердить что ты не робот

Компилировать и запускать динамический код без генерации EXE?

Мне было интересно, можно ли скомпилировать и запустить сохраненный код без генерации exe или любого другого файла, в основном запустить файл из памяти.

В основном, основное приложение будет иметь некоторый сохраненный код (код, который потенциально может быть изменен), и ему нужно будет скомпилировать код и выполнить его. без создания каких-либо файлов.

создание файлов, запуск программы, а затем удаление файлов не является опцией. скомпилированный код нужно будет запускать из памяти.

примеры кода или указатели или почти что угодно:)

4b9b3361

Ответ 1

using (Microsoft.CSharp.CSharpCodeProvider foo = 
           new Microsoft.CSharp.CSharpCodeProvider())
{
    var res = foo.CompileAssemblyFromSource(
        new System.CodeDom.Compiler.CompilerParameters() 
        {  
            GenerateInMemory = true 
        }, 
        "public class FooClass { public string Execute() { return \"output!\";}}"
    );

    var type = res.CompiledAssembly.GetType("FooClass");

    var obj = Activator.CreateInstance(type);

    var output = type.GetMethod("Execute").Invoke(obj, new object[] { });
}

Скомпилирует простой класс из строки исходного кода, затем создает экземпляр класса и рефлексивно вызывает на нем функцию.

Ответ 2

Вот пример использования System.Linq.Expressions для добавления в ответ Тима. Очевидно, что это не самый красивый код, но наличие его в этой красивой древовидной форме облегчает процесс разработки.

private  Expression<IsWordChar> CreateIsWordCharExpression()
{
    var e = Expression.Parameter(typeof(int), "e");
    var c = Expression.Variable(typeof(char), "c");
    var returnLabel = Expression.Label(Expression.Label(typeof(bool)), _falseConstant);
    var lambda = Expression.Lambda<IsWordChar>(
        Expression.Block(
            new[] { c },
            Expression.IfThen(
                Expression.OrElse(
                    Expression.Equal(e, Expression.Constant(-1)),
                    Expression.Equal(e, _inputLengthVar)
                ),
                Expression.Return(returnLabel.Target, _falseConstant)
            ),
            Expression.Assign(c, Expression.MakeIndex(_str, _stringCharsPropertyInfo, new[] { e })),
            Expression.IfThenElse(
                Expression.OrElse(
                    Expression.OrElse(
                        Expression.OrElse(
                            Expression.AndAlso(
                                Expression.GreaterThanOrEqual(c, Expression.Constant('a')),
                                Expression.LessThanOrEqual(c, Expression.Constant('z'))
                            ),
                            Expression.AndAlso(
                                Expression.GreaterThanOrEqual(c, Expression.Constant('A')),
                                Expression.LessThanOrEqual(c, Expression.Constant('Z'))
                            )
                        ),
                        Expression.AndAlso(
                            Expression.GreaterThanOrEqual(c, Expression.Constant('0')),
                            Expression.LessThanOrEqual(c, Expression.Constant('1'))
                        )
                    ),
                    Expression.Equal(c, Expression.Constant('_'))
                ),
                Expression.Return(returnLabel.Target, _trueConstant),
                Expression.Return(returnLabel.Target, _falseConstant)
            ),
            returnLabel
        ),
        "IsWordChar",
        new[] { e }
    );
    return lambda;
}

Ответ 3

Это возможно. Это легко или сложно, в зависимости от того, сколько и какой код вы хотите написать.

  • Скомпилируйте однострочные выражения: System.Linq.Expressions (простой, но ограниченный)
  • Скомпилировать целые программы: System.Reflection.Emit (трудно отлаживать, но не невозможно)

Изменить: Обратите внимание, что до .NET 4.0 System.Linq.Expressions ограничивается тем, что вы можете поместить в одну строку С#: то есть нет, если, while, назначение переменной и т.д.

Ответ 4

Да, вы можете это сделать. Это очень медленно, но вы можете это сделать. Посмотрите на CodeDOM или (new CSharpCodeProvider().CreateCompiler()) в .Net.

Ответ 5

Посмотрите System.CodeDom. Он будет делать именно то, что вы ищете.

Ответ 6

В Mono вы используете CSharp.Evaluator. Он действительно работает в памяти v. Некоторые из других упомянутых решений, которые выписывают и читают в файле под капотом.

Ответ 7

Также обратите внимание на встраивание языка сценариев, такого как Python, Ruby, Lua и т.д., все из которых поддерживают выполнение кода из памяти без записи на диск.

Ответ 8

Сложно, если не невозможно скомпилировать и выполнить С# без создания файла, потому что... Ну, то, что компиляция - превращение языка в исполняемый файл. То, что вы ищете, - это какая-то функциональность сценариев. То, что вы описали в своем вопросе, по существу, является разницей между интерпретированным языком и скомпилированным языком. См. Википедия: язык сценариев.

В зависимости от того, для чего вы будете использовать эту функцию, вы можете отлично использовать язык сценариев, такой как Python, Ruby или Lua. Вот пример: Как запустить Python script из С#?

Это заставило бы ваше приложение зависящее от python.exe(или любого исполняемого файла, который вам нужен, чтобы запустить выбранный вами язык скриптинга). Если вы хотите этого избежать, может быть, не слишком сложно сделать свой собственный язык сценариев, на котором ваше приложение выполняет время выполнения, в зависимости от того, что вам нужно делать с введенным script.

Изменить: этот первый абзац - мусор. Сожалею. См. http://msdn.microsoft.com/en-us/library/8ffc3x75%28v=vs.110%29.aspx