2.3 使用csc.exe构建C#应用程序
现在你开发用的计算机可以识别csc.exe了,下一个目标就是使用C#命令行编译器和记事本生成名为TestApp.exe的简单的单文件程序集。首先,需要一些源代码。打开记事本并键入以下内容:
// 一个简单的C#应用程序。
using System;
class TestApp
{
public static void Main()
{
Console.WriteLine("Testing! 1, 2, 3");
}
}
完成后把文件以TestApp.cs的名字保存在一个方便的地方(例如C:\CscExample)。现在,我们来了解C#编译器的核心选项。首先要明白如何指定要创建的程序集的名字和类型(例如,控制台应用程序命名为MyShell.exe,代码库命名为MathLib.dll、Windows Forms应用程序命名为MyWinApp.exe,等等)。各种选项可以通过将对应的具体标志作为命令行参数传入csc.exe来选择(如表2-2所示)。
为了把TestApp.cs编译成名为TestApp.exe的控制台应用程序,转到包含源代码文件的目录并键入以下命令(注意命令行标志必须位于导入的文件名字前面,不能在后面):
csc /target:exe TestApp.cs
这里没有明确指定/out标志,因而如果TestApp是定义程序入口点(Main()方法)的类,可执行文件将被命名为TestApp.exe。还要清楚的是,大多数C#编译器标志支持缩写版本,例如可以用/t代替/target(程序员可以在命令提示符下键入csc /?来查看所有的缩写):
csc /t:exe TestApp.cs
而且,因为/t:exe标志是C#编译器的默认输出,也可以仅仅通过键入下面的命令来编译TestApp.cs:
csc TestApp.cs
表2-2 C#编译器的输出选项
|
选 项 |
作 用 |
|
/out |
本选项用于指定将被构建出的程序集的名字。默认条件下,程序集的名字或者与最初输入的*.cs文件名字相同(生成*.dll文件的情况下),或者与包含程序的Main()方法的那个类型的名字相同(生成*.exe文件的情况下) |
|
/target:exe |
本选项构建一个可执行的控制台应用程序。这是默认的文件输出类型,并且在创建该应用程序类型时可被忽略 |
|
/target:library |
本选项构建一个单一文件*.dll程序集 |
|
/target:module |
本选项构建一个模块(module)。所谓模块是指组成多文件程序集的元素(详细内容见第11章) |
|
/target:winexe |
本选项构建一个可执行的Windows应用程序。尽管使用/target:exe也能创建窗体应用程序,但本选项创建的程序运行时不会有控制窗口出现在桌面背景上 |
现在TestApp.exe可以从命令行运行了(如图2-1所示)。

图2-1 .TestApp在运行
2.3.1 引用外部程序集
接下来,让我们考查如何编译一个应用程序,如果它采用了在另一个.NET程序集里定义的类型。说到这里,如果你想知道C#编译器是如何理解对于System.Console类型的引用的,请回忆一下第1章里mscorlib.dll在编译过程期间是如何被自动引用的(如果由于特别的原因希望禁用这个功能,可以指定/nostdlib标志)。
为了阐明引用外部程序集的过程,让我们修改TestApp应用程序,显示一个Windows窗体消息框。打开TestApp.cs文件并做如下修改:
using System;
// 一定要加上这一行!
using System.Windows.Forms;
class TestApp
{
public static void Main()
{
Console.WriteLine("Testing! 1, 2, 3");
// 一定要加上这一行!
MessageBox.Show("Hello...");
}
}
注意,对System.Windows.Forms命名空间的引用是通过C# using关键字实现的(该关键字介绍见第1章)。回忆一下,如果显式地列出在一个给定的*.cs文件里所用到的命名空间,就可以避免采用完全限定名(否则你会累到手抽筋)。
在命令行中,必须通知csc.exe,哪个程序集包含了“所用的”命名空间。假定你已经使用了MessageBox类,必须使用/reference标志指定System.Windows.Forms.dll程序集(/reference标志可以缩写为/r):
csc /r:System.Windows.Forms.dll testapp.cs
如果现在再次运行应用程序,除了控制台输出以外还可以看见图2-2里出现的内容。
2.3.2 使用csc.exe编译多个源文件
TestApp.exe应用程序的当前版本是用单个*.cs源代码文件创建的。在单个的*.cs文件里定义所有.NET类型是完全允许的,然而大多数项目由多个*.cs文件组成,以使代码库更为灵活。假定你又编写了一个类,包含在名为HelloMsg.cs的新文件里:
// HelloMessage类。
using System;
using System.Windows.Forms;
class HelloMessage
{
public void Speak()
{
MessageBox.Show("Hello...");
}
}
现在,修改初始的TestApp类以使用这种新的类型,并且注释掉以前的Windows窗体代码:
using System;
// 不再需要这一行了。
// 使用System.Windows.Forms;
class TestApp
{
public static void Main()
{
Console.WriteLine("Testing! 1, 2, 3");
// 也不再需要这一行了。
// MessageBox.Show("Hello...");
// 练习一下HelloMessage类。
HelloMessage h = new HelloMessage();
h.Speak();
}
}
可以通过显式地列出各个导入文件来编译C#文件:
csc /r:System.Windows.Forms.dll testapp.cs hellomsg.cs
另外,C#编译器还允许使用通配符(*)通知csc.exe,包含所有位于项目目录里的*.cs文件作为当前构建的一部分。
csc /r:System.Windows.Forms.dll *.cs
当再次运行程序时,输出完全相同。两个应用程序的唯一差别在于,当前代码分到了多个文件中。
2.3.3 引用多个外部程序集
顺带说明,如果需要csc.exe引用大量的外部程序集会怎样呢?仅需使用一个用分号划界的列表列出各个程序集。对上面这个例子不需要指定多个外部程序集,但我们还是给出一个示例用法:
csc /r:System.Windows.Forms.dll;System.Drawing.dll *.cs






