Building C# Applications: The C# Command-Line Compiler (CSC - Exe)
Building C# Applications: The C# Command-Line Compiler (CSC - Exe)
When you use graphical IDEs to build applications, you are ultimately instructing csc.exe how to manipulate your C# input files. In this light, its edifying to see what takes place behind the scenes. Another nice by-product of working with csc.exe in the raw is that you become that much more comfortable manipulating other command-line tools included with the .NET Framework 2.0 SDK. As you will see throughout this book, a number of important utilities are accessible only from the command line.
To compile TestApp.cs into a console application named TestApp.exe, change to the directory containing your source code file and enter the following command set (note that command-line flags must come before the name of the input files, not after): csc /target:exe TestApp.cs Here /out flag is not explicitly specified, therefore the executable will be named TestApp.exe, given that TestApp is the class defining the programs entry point (the Main() method). Also be aware that most of the C# compiler flags support an abbreviated version, such as /t rather than /target (you can view all abbreviations by entering csc /? at the command prompt): csc /t:exe TestApp.cs Furthermore, given that the /t:exe flag is the default output used by the C# compiler, you could also compile TestApp.cs simply by typing csc TestApp.cs
Lets examine how to compile an application that makes use of types defined in a separate .NET assembly. Speaking of which, just in case you are wondering how the C# compiler understood your reference to the System.Console type, recall from Chapter 1 that mscorlib.dll is automatically referenced during the compilation process To illustrate the process of referencing external assemblies, lets update the TestApp application to display a Windows Forms message box. Open your TestApp.cs file and modify it as follows:
using System; // Add this! using System.Windows.Forms; class TestApp { public static void Main() { Console.WriteLine("Testing! 1, 2, 3"); // Add this! MessageBox.Show("Hello..."); } }
Notice the reference to the System.Windows.Forms namespace via the C# using keyword (introduced in Chapter 1). Recall that when you explicitly list the namespaces used within a given *.cs file, you avoid the need to make use of fully qualified names (which can lead to hand cramps).
At the command line, you must inform csc.exe which assembly contains the used namespaces. Given that you have made use of the MessageBox class, you must specify the System.Windows. Forms.dll assembly using the /reference flag (which can be abbreviated to /r): csc /r:System.Windows.Forms.dll testapp.cs
If you now rerun your application, you should see what appears in Figure 2-2 in addition to the console output.
// The HelloMessage class using System; using System.Windows.Forms; class HelloMessage { public void Speak() { MessageBox.Show("Hello..."); } }
Now, update your initial TestApp class to make use of this new type, and comment out the previous Windows Forms logic:
using System; // Don't need this anymore. // using System.Windows.Forms; class TestApp { public static void Main() { Console.WriteLine("Testing! 1, 2, 3"); // Don't need this anymore either. // MessageBox.Show("Hello..."); // Exercise the HelloMessage class! HelloMessage h = new HelloMessage(); h.Speak(); } } You can compile your C# files by listing each input file explicitly: csc /r:System.Windows.Forms.dll testapp.cs hellomsg.cs As an alternative, the C# compiler allows you to make use of the wildcard character (*) to inform csc.exe to include all *.cs files contained in the project directory as part of the current build: csc /r:System.Windows.Forms.dll *.cs When you run the program again, the output is identical. The only difference between the two applications is the fact that the current logic has been split among multiple files.