实现C#即时编译器
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实现C#即时编译器
结合控制台重定向和C#即使编译器(见我上⾯两篇⽂章)写的WinForm即时C#编译器,功能还不错。
⽂本框就是你Main⽅法内的语句,可以输⼊任意测试代码,⽀持错误⾏号定位,编译结果捕获,⾃动拆分窗格等,程序按F5执⾏,F5……忘记在代码⾥⾯加说明了:( 时间不早了,上传睡觉,带批处理build代码和SharpDevelop⽅式源代码哦。
可以拿下⾯的代码测试程序
//F5: Compile and Run the app F6:Kill current Running App
//-----------------------------------------------------------
System.Diagnostics.Process.Start("notepad");
//test Generic Collection
List<int> lstInt = new List<int>{
1,3,5,7,9,11
};
foreach(var v in lstInt)
Console.WriteLine(v);
//test Timer
System.Timers.Timer timer = new System.Timers.Timer(1000);
timer.Elapsed += delegate{
System.Console.WriteLine(DateTime.Now.TimeOfDay.ToString());
};
timer.Start();
Console.ReadKey();
//test WinForm Application
//Application.Run(new Form());
这个程序⽤了我两天的时间,涉及到技术有:
1、同线程的控制台重定向到⽂本框
2、不同线程的控制台重定向到⽂本框-异步⽅式
3、编译代码并执⾏(Invoke⽅式和Process⽅式)
4、结束进程树
5、⽂件操作等
实现编译器的代码如下:
//#define CompileIntoMemory
using System;
using piler;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace PhoenixCompiler
{
///<summary>
/// director the Console output to ListBox
/// in MainForm Construction:
///</summary>
public class PhoenixWriter : System.IO.TextWriter
{
delegate void VoidAction();
System.Windows.Forms.TextBox txtBox;
public PhoenixWriter(System.Windows.Forms.TextBox box)
{
this.txtBox = box;
}
public override System.Text.Encoding Encoding {
get { return System.Text.Encoding.UTF8;}
}
//here, must use parameter: char value
public override void Write(char value)
{
VoidAction action = delegate{
txtBox.AppendText(value.ToString());
};
txtBox.BeginInvoke(action);
}
}
///<summary>
/// Description of PhoenixCompiler.
///</summary>
public class PhoenixCompiler
{
public PhoenixCompiler()
{
}
public string GenerateCode(string userCode)
{
string namespaces =@"using System;
using ponentModel;
using System.Text;using System.Text.RegularExpressions;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms
;using System.Threading;
using System.Reflection;
";
string codeHead = @"
sealed class Phoenix
{
public static void Main()
{
//----------your code here-----------
";
//userCode here
string codeTail = @"
//----------your code here-----------
}
}
";
string compileCodes = namespaces + codeHead + userCode + codeTail;
return compileCodes;
}
public CompilerResults Compile(string codes)
{
//CSharpCodeProvider
piler.CodeDomProvider compiler = new Microsoft.CSharp.CSharpCodeProvider();
//CompilerParameters
pilerParameters parameters = new CompilerParameters();
parameters.WarningLevel = 4;
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
#if CompileIntoMemory
parameters.GenerateInMemory = true;
#else
parameters.GenerateExecutable=true;
#endif
return pileAssemblyFromSource(parameters,codes);
}
}
///<summary>
/// Description of MainForm.
///</summary>
public partial class MainForm : Form
{
System.Diagnostics.Process process;
public MainForm()
{
InitializeComponent();
//redirector Console output to ListBox lstResult
Console.SetOut(new PhoenixWriter(txtResult));
}
//KillProcessTreeById
public void KillProcessTreeById(int parentId)
{
//find all the process id created by parentId, Saved it to List childIds
System.Collections.Generic.List<int> childIds=
new System.Collections.Generic.List<int>();
System.Diagnostics.Process[] processes =
System.Diagnostics.Process.GetProcesses();
foreach (var element in processes) {
string path = string.Format("win32_process.handle='{0}'",element.Id);
using (var mo= new System.Management.ManagementObject(path)) {
try {
mo.Get();
} catch (System.Management.ManagementException me) {
throw me;
}
int id=Convert.ToInt32(mo["ParentProcessId"]);
if (id==parentId) {
childIds.Add(element.Id);
}
}
}
foreach (var element in childIds) {
//Console.WriteLine(element);
System.Diagnostics.Process processKill =
System.Diagnostics.Process.GetProcessById(element);
if (processKill.ProcessName !="conhost") {
processKill.Kill();
}
//processKill.CloseMainWindow();
//processKill.Close();
}
var processParent = System.Diagnostics.Process.GetProcessById(parentId);
if (processParent !=null) {
processParent.Kill();
}
}
void TxtCodeKeyDown(object sender, System.Windows.Forms.KeyEventArgs e) {//F5:116 e.KeyCode.ToString() + ":" + e.KeyValue.ToString();
if (e.KeyValue == 116) {
if (process!=null) {
this.KillProcessTreeById(process.Id);
process=null;
}
PhoenixCompiler compiler = new PhoenixCompiler();
string code = compiler.GenerateCode(txtCode.Text);
pilerResults result = pile(code);
ShowResult(result);
}
if (e.KeyValue==117) {//F6:117 here should terminate the process tree ... ...
if (process != null) {
this.KillProcessTreeById(process.Id);
process=null;
}
}
}
public void ShowResult(pilerResults result)
{
txtResult.Text="";
Console.WriteLine("Phoenix Compiler! \r\n\tCopyright by XUMINGHUI(2013)");
Console.WriteLine("-----------------------------------------------\n");
if (result.Errors.HasErrors) {
Console.WriteLine("Build ERROR:\r\n");
foreach (pilerError error in result.Errors) {
Console.WriteLine(error.Line + ":" + error.ErrorText);
}
return;
}
//build OK
Console.WriteLine("Build Successfully:\r\n");
try {//call Main entry, Console output --> WinForm Control
#if CompileIntoMemory
Type Phoenix = piledAssembly.GetType("Phoenix");
Phoenix.GetMethod("Main").Invoke(null,new string[]{});
#else//start another thread to run the generated application
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo{ FileName=result.PathToAssembly,
UseShellExecute=false,
CreateNoWindow=true,
RedirectStandardError=true,
RedirectStandardOutput=true
};
process = new System.Diagnostics.Process();
process.OutputDataReceived +=(s,e)=>{
if (e.Data!=null) {
Console.WriteLine(e.Data);
}
};
process.ErrorDataReceived +=(s,e)=>{
if (e.Data!=null) {
Console.WriteLine(e.Data);
}
};
process.StartInfo = info;
process.EnableRaisingEvents = true;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
#endif
} catch (System.Reflection.TargetInvocationException ex) {
Console.WriteLine("Exception:" + ex.InnerException.Message);
}
}
void MainFormFormClosing(object sender, FormClosingEventArgs e)
{
if (process != null) {
this.KillProcessTreeById(process.Id);
process=null;
}
}
void TxtResultDoubleClick(object sender, EventArgs e) {
if (txtResult.Text=="") {
return;
}
string path = System.IO.Path.GetTempFileName();
System.IO.File.AppendAllText(path,txtResult.Text); System.Diagnostics.Process.Start("notepad",path); }
void TxtCodeDoubleClick(object sender, EventArgs e) {
PhoenixCompiler compiler = new PhoenixCompiler();
string code = compiler.GenerateCode(txtCode.Text);
string path = System.IO.Path.GetTempFileName();
System.IO.File.AppendAllText(path,code);
System.Diagnostics.Process.Start("notepad",path); }
}
}。