惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
Cyberwarzone
Cyberwarzone
T
Tenable Blog
Security Latest
Security Latest
NISL@THU
NISL@THU
V
Vulnerabilities – Threatpost
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
W
WeLiveSecurity
罗磊的独立博客
Stack Overflow Blog
Stack Overflow Blog
云风的 BLOG
云风的 BLOG
Martin Fowler
Martin Fowler
Engineering at Meta
Engineering at Meta
T
Tor Project blog
H
Heimdal Security Blog
Microsoft Security Blog
Microsoft Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
雷峰网
雷峰网
L
LINUX DO - 热门话题
The GitHub Blog
The GitHub Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Recorded Future
Recorded Future
Hugging Face - Blog
Hugging Face - Blog
P
Privacy & Cybersecurity Law Blog
F
Full Disclosure
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
PCI Perspectives
PCI Perspectives
MyScale Blog
MyScale Blog
B
Blog RSS Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
K
Kaspersky official blog
Attack and Defense Labs
Attack and Defense Labs
H
Hackread – Cybersecurity News, Data Breaches, AI and More
有赞技术团队
有赞技术团队
Know Your Adversary
Know Your Adversary
Hacker News - Newest:
Hacker News - Newest: "LLM"
Scott Helme
Scott Helme
The Last Watchdog
The Last Watchdog
博客园 - 【当耐特】
S
Security Affairs
The Cloudflare Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
人人都是产品经理
人人都是产品经理
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
N
News and Events Feed by Topic
AI
AI
H
Help Net Security
美团技术团队
T
Threatpost
Project Zero
Project Zero

博客园 - sunjie

关于C#中async/await中的异常处理(上) 入门教程: JS认证和WebAPI ASP.NET Core 之 Identity 入门(二) 在Visual Studio 2017中使用Asp.Net Core构建Angular4应用程序 .Net Core+Angular Cli/Angular4开发环境搭建教程 简单易用的.NET免费开源RabbitMQ操作组件EasyNetQ解析 Razor - 模板引擎 / 代码生成 - RazorEngine 一个简易的反射类库NMSReflector 发布 Ionic iOS 企业级应用 AngularJS中的Provider们:Service和Factory等的区别 Angular $scope和$rootScope事件机制之$emit、$broadcast和$on Ionic开发实战 Entity Framework 5.0 Code First全面学习 6个强大的AngularJS扩展应用 使用npm安装一些包失败了的看过来(npm国内镜像介绍) 自己家里搭建NAS服务器有什么好方案? 使用Visual Studio Code搭建TypeScript开发环境 Office web app server2013详细的安装和部署 谈谈家庭装修中强电回路设计以及电线空开配套
自己动手制作CSharp编译器
sunjie · 2016-10-18 · via 博客园 - sunjie

Posted on 2016-10-18 16:22  sunjie  阅读(5461)  评论()    收藏  举报

  1. 在你喜欢的位置(如F盘根目录)新建一个文件夹,并命名为“CSharp开发环境”。找到或下载C#编译器组件(csc.exe和cscui.exe),并放在先前建立的文件夹中。该组件的一般位置在C盘的.NET文件夹中,如“C:\Windows\Microsoft.NET\Framework\v4.0.30319”,最后一个为版本号,可根据你的需要选择。同时在这个文件夹中还有我们需要的类库(System.dll),找到并复制到“CSharp开发环境\lib”文件夹中。

  2. 2

    为了能够在控制台下找到我们的编译器,下面设置环境变量Path。右击桌面的计算机->点击属性->点击高级选项卡中的环境变量->在用户环境变量选中Path并点击编辑->添加“F:\CSharp开发环境;”->点击OK即可。如下图:

    自己动手制作CSharp编译器

  3. 3

    测试。打开控制台(如果你用到是Win8,可以 Win+X ->C 快速打开控制台),并输入csc,若出现下图结果即表示正常。

    自己动手制作CSharp编译器

    END

编写代码

  1. 1

    在你喜欢的位置(例如,“F:\CSharp开发环境\project”目录)中建立一个文件夹,并命名为“cc”,该目录便是我们存放源代码的目录。

  2. 2

    添加源文件。在cc目录中新建“cc.cs”文件,并用文本编辑器打开,并输入以下代码:

    using System;

    using System.IO;

    using System.CodeDom;

    using System.CodeDom.Compiler;

    using Microsoft.CSharp;

    namespace CC{

    public class CC{

    public static void Main(string[] args){

    if(args.Length==0){

    Console.WriteLine("该工具的正确使用方法是:cc 源文件");

    Console.Read();

    return;

    }

    FileInfo sourceFile=new FileInfo(args[0]);

    CodeDomProvider provider=null;

    if(sourceFile.Extension.ToUpper()==".CS"){

    provider=CodeDomProvider.CreateProvider("CSharp");

    }

    else if(sourceFile.Extension.ToUpper()==".VB"){

    provider=CodeDomProvider.CreateProvider("VisualBasic");

    }

    else{

    Console.WriteLine("错误1:源代码文件必须以“.cs”或“.vb”为后缀");

    }

    if(provider !=null){

    string exeName=String.Format(@"{0}\{1}.exe",Environment.CurrentDirectory,sourceFile.Name.Replace(".","_"));

    CompilerParameters cp=new CompilerParameters();

    cp.GenerateExecutable=true;

    cp.OutputAssembly=exeName;

    cp.GenerateInMemory=false;

    CompilerResults cr=provider.CompileAssemblyFromFile(cp,args[0]);

    if(cr.Errors.Count > 0){

    Console.WriteLine("Errors building {0} into {1}",args[0], cr.PathToAssembly);

    foreach(CompilerError ce in cr.Errors)

    {

    Console.WriteLine("  {0}", ce.ToString());

    Console.WriteLine();

    }

    }

    else

    {

    Console.WriteLine("Source {0} built into {1} successfully.",args[0], cr.PathToAssembly);

    }

    }

    Console.Write("Press any key to exit...");

    Console.Read();

    }

    }

    }

  3. 3

    代码解释。

    前5行代码是名称空间的引用,我们使用的最重要的类便在System.CodeDom.Compiler中。

    6-8行分别定义名称空间、类和入口函数。

    9-13行是对命令行参数的检验,为了简单,本文设定只有第一个参数有效,并且便是源文件名。

    14-15行定义两个非常重要的变量,一个表示源文件的变量sourceFile(FileInfo),其参数从上一步中得到,即命令行第一个参数。另一个表示编译器的变量provider(CodeDomProvider,使用CompileAssemblyFromFile方法即可把源文件编译成目标文件),并初始化为null。

    17-25行使用“工厂模式”得到CodeDomProvider的实例,即根据后缀初始化为VB编译器还是C#编译器。注意:本文只考虑C#代码,若您还想编译VB代码只需添加相应的引用即可。

    27行是对provider的检验,若不为空则则可以继续编译。这是避免空引用异常的常用方法。28-34行定义编译选型,即CompilerParameters类。GenerateExecutable=true表示生成可执行文件,若为false表示生成类库;OutputAssembly表示生成的文件。

    35行调用provider.CompileAssemblyFromFile(编译选项,源文件)方法生成可执行文件,并得到CompilerResults类的一个实例,该实例表示编译结果。

    36行以后是对编译结果的处理,若有错则输出错误,若成功则提示生成成功。

  4. 4

    编译。我们可以在命令行下直接编译,而为了在调试时不必重复输入相同的命令,我们可以做一个批处理。新建文本文件并重命名为“MakeFile.bat”,添加如下代码:

    csc cc.cs /reference:%Lib%\System.dll

    pause

    然后双击运行,若没有错误的话就会得到“cc.exe”文件。

    注意:为了方便的引用类库,我们需要添加环境变量,“Lib=F:\CSharp开发环境\lib”,注意这里没有分号而且只有这一个值(这是为了在写批处理文件时方便采这么设定的)。

    END

测试

  1. 为了测试我们做的“编译器”,我们在project目录中添加hello工程(一个文件夹),并添加源代码文件“hello.cs”,hello.cs的内容为:

    using System;

    namespace Test{

    public class Test{

    public static void Main(string[] arg){

    Console.WriteLine("Hello world");

    Console.ReadLine();

    }

    }

    }

    然后,我们把得到的cc.exe文件复制到当前目录中。 同样的,我们也建立一个“MakeFile.bat”文件,代码如下:

    cc hello.cs

    pause

    双击该批处理,若没有错误的话即可得到一个可执行文件(hello_cs.exe),如下:

    自己动手制作CSharp编译器

  2. 2

    执行“hello_cs.exe”文件,如图:

    自己动手制作CSharp编译器