2016-08-03 2 views
0

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

Способ, которым вы будете запускать это «SecureCodeBridge.exe File.txt», этот текстовый файл содержит код, который создает и показывает форму окна, которая отлично работает.

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

Это код моего консольного приложения:

static void Main(string[] args) 
{ 
    string entString = args[0]; 

    if(System.IO.File.Exists(entString)) 
    { 
     string entContents = System.IO.File.ReadAllText(entString); 
     SecureCode sC = new SecureCode(entContents); 
     CompilerResults cR = sC.Compile(); 

     if(cR.Errors.Count > 0) 
     { 
      //Abort! 
      foreach(CompilerError cE in cR.Errors) 
      { 
       Console.WriteLine(cE.ErrorText); 
      } 
     } 
     else 
     { 
      sC.Run(cR); 
     } 
    } 
} 

и это код моя структура использует для компиляции и выполнения кода:

public class SecureCode 
{ 
    string code; 
    public SecureCode(string source) 
    { 
     code = source; 
    } 

    public CompilerResults Compile() 
    { 
     Dictionary<string, string> providerOptions = new Dictionary<string, string> 
     { 
      {"CompilerVersion", "v3.5"} 
     }; 
     CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions); 

     CompilerParameters compilerParams = new CompilerParameters 
     { 
      GenerateInMemory = true, 
      GenerateExecutable = false 
     }; 
     compilerParams.ReferencedAssemblies.Add("System.dll"); 
     compilerParams.ReferencedAssemblies.Add("System.Windows.Forms.dll"); 
     compilerParams.ReferencedAssemblies.Add("System.Drawing.dll"); 

     CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, code); 

     return results; 
    } 

    public void Run(CompilerResults results) 
    { 
     object o = results.CompiledAssembly.CreateInstance("Code.Class"); 
     MethodInfo mi = o.GetType().GetMethod("Main"); 
     mi.Invoke(o, null); 
    } 
} 

ли существует ли способ сохранить консольное приложение в активном состоянии при вызове метода? (Например, форма показана)

ответ

2

Invoke будет ждать методу завершения, BeginInvoke будет работать асинхронно, так что ваш метод является завершения (например, открытие формы), а затем консольное приложение покидает ,

Если вы хотите ждать приложения/сборок вы формованные до выхода, то вы можете запустить его как процесс (System.Diagnostics), вам нужно будет думать, как вы получите ваш скомпилированный код, чтобы вызываемым формат:

var process = Process.Start(<options>); 
process.WaitForExit(); 

Другим вариантом было бы повесить на нерабочую ссылку, я не запустить ниже, но это не должно быть далеко. не Вы бы цикл, пока слабая ссылка не очищается после того, как объект больше не считается уместной сборщика мусора:

WeakReference(weakRef = new WeakReference(results.CompiledAssembly.CreateInstance("Code.Class")); 
MethodInfo mi = weakRef.Target.GetType().GetMethod("Main"); 
mi.Invoke(o, null); 

// Wait until the application exists AND the Garbage Collector cleans it up 
while (weakRef.IsAlive) 
{ 
    Thread.Sleep(100); 
} 

Последний вариант я могу думать о том, чтобы собрать в обработчик событий (скажем OnExit или OnClose()), а затем подключите его через отражение с механизмом ожидания в консольном приложении, чтобы закрыть, когда он получит обратный вызов. From this post.

// Получите EventInfo, представляющий событие Click, и получите // тип делегата, который обрабатывает событие. // EventInfo evClick = tExForm.GetEvent («Клик»); Тип tDelegate = evClick.EventHandlerType;

// If you already have a method with the correct signature, 
// you can simply get a MethodInfo for it. 
// 
MethodInfo miHandler = 
    typeof(Example).GetMethod("LuckyHandler", 
     BindingFlags.NonPublic | BindingFlags.Instance); 

// Create an instance of the delegate. Using the overloads 
// of CreateDelegate that take MethodInfo is recommended. 
Delegate d = Delegate.CreateDelegate(tDelegate, this, miHandler); 

// Get the "add" accessor of the event and invoke it late- 
// bound, passing in the delegate instance. This is equivalent 
// to using the += operator in C#, or AddHandler in Visual 
// Basic. The instance on which the "add" accessor is invoked 
// is the form; the arguments must be passed as an array. 
// 
MethodInfo addHandler = evClick.GetAddMethod(); 
Object[] addHandlerArgs = { d }; 
addHandler.Invoke(exFormAsObj, addHandlerArgs); 

Удачи вам!

+0

Я попробовал второй метод, но пока он сохраняет приложение консоли (заморожено), он также заморозит форму, любые идеи? (попробовал запустить его в другом потоке, но затем мы вернемся к квадрату с формой, выходящей все время). – user265889

+0

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