#c_sharp #windows #winforms #файлы #компилятор
Приветствую. Не знаю в какую сторону копать и возможно ли такое вообще. Суть задачи такова : есть приложение написанное на c# в windowsforms. В приложении пользователь задает некоторые параметры, указывает пути к картинке ect и после выполнения всех настроек родительское приложение собирает в папке рядом с собой еще одно exe программу но значительно урезанную согласно установкам пользователя. Можно ли такое сделать если да то в какую сторону рыть, чем гугол мучать ?
Ответы
Ответ 1
Нашел небольшой пример по теме. Если кому будет интересно вот код с динамической компиляцией (exe создается из exe) : using System; using System.CodeDom.Compiler; using System.Collections.Generic; using Microsoft.CSharp; namespace ConsoleCompiler { internal class Program { private static void Main(string[] args) { // Source code для компиляции string source = @" namespace Foo { public class Bar { static void Main(string[] args) { Bar.SayHello(); System.Console.ReadKey(); } public static void SayHello() { System.Console.WriteLine(""Hello World""); } } }"; // Настройки компиляции DictionaryproviderOptions = new Dictionary { {"CompilerVersion", "v3.5"} }; CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions); CompilerParameters compilerParams = new CompilerParameters { OutputAssembly = "D:\\Foo.EXE", GenerateExecutable = true }; // Компиляция CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, source); // Выводим информацию об ошибках Console.WriteLine("Number of Errors: {0}", results.Errors.Count); foreach (CompilerError err in results.Errors) { Console.WriteLine("ERROR {0}", err.ErrorText); } Console.ReadKey(); } } } Сам вопрос можно закрывать. Ответ 2
Компиляция нового приложения - довольно тяжелый вариант, из разряда "из пушки по воробьям". Особенно "весело" в такой программе будет экранировать константы в коде... Можно поступить проще. Для начала, можно просто отдавать копировать текущую программу (или лежащую рядом), но с измененным конфигом. Это намного проще всех остальных вариантов. Если же принципиально нужно забить настройки в код, то можно сделать вот так: Готовим библиотеку с точкой входа, которая будет принимать все нужные настройки: public sealed class Program { public string Foo { get; set; } public int Bar { get; set; } public void Run() { // ... } } Создаем выражение на создание объекта с зашитыми настройками: var configExpr = Expression.MemberInit( Expression.New(typeof(Program)), Expression.Bind(typeof(Program).GetProperty("Foo"), Expression.Constant("Hello, world!")), Expression.Bind(typeof(Program).GetProperty("Bar"), Expression.Constant(42))); Создаем программу-загрузчик через Reflection.Emit: var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Loader"), AssemblyBuilderAccess.Save); var moduleBuilder = assemblyBuilder.DefineDynamicModule("Main", "Loader.exe"); var type = moduleBuilder.DefineType("Loader", TypeAttributes.Abstract | TypeAttributes.Sealed); var method = type.DefineMethod("Main", MethodAttributes.Static); Expression.Lambda(Expression.Call(configExpr, "Run", null)).CompileToMethod(method); type.CreateType(); assemblyBuilder.SetEntryPoint(method, PEFileKinds.WindowApplication); assemblyBuilder.Save("Loader.exe"); Как видно, код получился заметно короче чем вариант с использованием CodeDOM. И безопаснее.
Комментариев нет:
Отправить комментарий