Not so long ago the guys here at CP announced a new Cross Platform .NET section. At the time I was working completely with Windows based applications using C# and the .NET platform so, while the thought of getting to play around with C# apps on other platforms was interesting, it wasn't something I had the time to do. Nevertheless, fate has once again stepped in, this time in the form of a new project, and soon I'll be working on systems that will no doubt require some cross platform goodness. Since the majority of the development will still be for the Windows platform the technology set will be staying as is and the happiness that exists when developing .NET applications will remain.
Anyway, it dawned on me that I didn't really know all that much about cross platform development with .NET. Sure, I had heard of Mono, Rotor and Platform.NET and had read some things here and there but I didn't have any practical knowledge about using any of these. After a bit of research I decided that Mono was the most promising choice for the upcoming project and I decided to give it a go. I am fairly familiar with Linux and have developed applications, albeit basic ones, for Linux using C, C++ and Java when in college. However, many weblog postings from bemused Windows developers who had attempted to get Mono up and running on Linux had me slightly worried before I began. Much to my surprise, it was actually a painless experience and getting Mono running on Linux was easy. Setting it up and running it on Windows was even easier again.
What exactly is Mono?
When Microsoft unleashed .NET onto the world they were nice enough to hand the Common Language Infrastructure (CLI), along with the C# language, to the people at the European Computer Manufactures Association, better known to most as the ECMA. This allowed for an ECMA standards for the CLI and C# to be developed and, eventually, these ECMA standards also became ISO standards. At this stage you might be thinking "So, what has this got to do with what Mono is?" Relax, slow down, I'm getting to it. This standardization meant that details about how a CLI implementation should work, and also details about the C# programming language, where publicly available and anybody with the time and desire could implement their own CLI, essentially making their own version of .NET. Mono was born.
Mono is an "open source development platform based on the .NET framework that allows developers to build Linux and cross-platform applications with unprecedented productivity". At the time of writing this article the latest stable version of Mono is 1.0.5 and it provides the following features:
- A Common Language Runtime (CLR) that is compatible with the ECMA standard
- A C# compiler
- A set of class libraries
- Ancillary tools such as a disassembler, debugger, IDE, etc.
Although it may not sound like much to many, what the people behind the Mono project have achieved is quite impressive. The set of class libraries available with mono include implementations of ADO.NET, ASP.NET, and System.Windows.Forms as well as many other aspects of the BCL that .NET developers will be familiar with. Added to this is the Gtk# library which is a fully featured library that allows for the development of GUI apps on top of the gtk+ toolkit. All in all, quite impressive.
With Mono you can develop and run .NET applications on Linux, Windows and other platforms. You can build and deploy ASP.NET application on Linux servers. You can even run applications that you compiled using the Microsoft C# compiler on the Mono runtime and vice versa.
What is the purpose of this article?
This article is the first in a series of articles that I will be writing about developing cross platform applications using Mono. Its purpose is to explain how to get up and running with Mono on Linux and on Windows. I'll explain how you install Mono and then I'll show you how to use the C# compiler to compile and run what might be your first cross platform .NET application. I'll also list some of the ancillary tools that come with Mono. Finally, I'll show how you can run applications created using Mono on the Microsoft .NET Runtime and vice versa.
Unfortunately I haven't had a chance to play with Mono on a Mac so I won't be covering it in this article. However I will try to cover it, along with Platform.NET, in a future article. No promises though.
What you need to know
This article is not going to show you how to program in C#. This is something that you will have to learn yourself. There are many good introductory articles here on CP that you can read to gain a firm understanding of the ins and outs of the language.
An understanding of what the .NET Framework and what it is is not necessary, but it would definitely be beneficial.
Lets get going
Before you can develop anything using Mono you first need to get it up and running on your desired platform. Since this article is in the Cross Platform .NET section and one of the main uses of Mono is the development and use of cross platform applications, I cover installing Mono on both Windows and Linux. I'll look at installing on Windows first even though, to be perfectly honest, it's a bit of a no brainer. As I mentioned above, the latest stable version of Mono at the time of writing this article is 1.0.5 and I will be working with this version. The download page for the latest Mono releases is http://www.mono-project.com/downloads/index.html[^] but I will be giving direct links to the files I download in each of the sections.
If you would prefer to skip installing Mono on Windows then you can go straight to the Installing Mono on Linux section below.
Installing Mono on Windows
The Windows version of Mono runs on Windows 2000 and above. I'm working on Windows XP Professional with Service Pack 2 installed. It probably doesn't make a difference but I just wanted to mention it in case my instructions on installing Mono on Windows differs slightly from the procedure you need to follow for your own setup. Just follow these steps and you should be up and running in no time:
- Download the Mono Windows Installer from the Mono download page. The file I am working off is http://www.go-mono.com/archive/1.0.5/windows/mono-1.0.5-gtksharp-1.0.5-win32-0.1.exe
- The installer is a standard Windows installer so you can simply run it once it is downloaded by doubling clicking on it.
- Once the installer begins, click on next to go to the License Agreement page.
- You'll probably notice on the License Agreement page that there are a number of different Licenses that apply to the different components of the install. While I understand that most people simply agree and click on next, it would be irresponsible of me if I didn't recommend that you read the License Agreement before agreeing to it.
- Once you pass the License Agreement section you are presented with some general information about the install. The installer that I link to above mentions that it includes Gtk# and XSP (A Mono based web server that I will be looking at in the next article in this series) among other things.
- Click on Next and select the install location.
- Click on Next again to bring you to the Select Components page. You are free to customize your installation but as I will be using all the components of this install in other articles in this series I would suggest that you accept the default "Full installation".
- Click on Next again and you can customize the name of Mono folder that appears in the Start Menu.
- If you have decided to do a Full installation or if you have installed XSP, the installer will now ask you which port you want the web server to listen on. Generally this will be port 8088 but you can change it to any free port on your system. When you are ready click on Next.
- Finally, click on Install to install and configure Mono on your Windows machine.
The above list of instructions is probably too verbose. Most people would have been fine just clicking on Next the whole way through. However, I normally take my time when installing things. You never know what people slip into an installer and it's always good to know exactly what you have put on your machine.
At this stage you can keep reading and learn how to install Mono on your Linux machine or if you don't have a Linux installation, or just want to develop on Windows for the time being, you can skip ahead to the Your Mono toolset section.
Installing Mono on Linux
Linux is a great operating system. There is no doubting that. However, there are some basic problems with the Linux platform that have stemmed from the fact that the kernel and most of the supporting software is open source. The problem is a simple one; there are so many different Linux distributions that there is no single set way of installing software on them. Why should you care about this? Well, depending on the distribution that you use, it could end up making your life a little more complicated then it needs to be when installing Mono. You'll see what I mean below.
To get Mono up and running I decided to go for one of the more popular Linux distributions. Partly because I was familiar with it and partly because there was already an iso of the installation DVD on one of the internal FTP servers in work. No point in downloading a different distribution if I have a perfectly good one here. So, what did I choose? SuSE 9.2 Professional. I used Microsoft Virtual PC 2004 to create two identical virtual PCs. Two because I wanted to try two different ways of installing and configuring Mono that were not mutually exclusive. I didn't want them to interfere so I decided that two separate virtual PCs was the way to go. I mounted the installation DVD iso in the virtual PCs and went about installing an identical system on both virtual PCs. I chose to install with ACPI disabled, which is one of the first options you get to choose, and I went for the default package selection. Nothing fancy. Just the basic, default system that SuSE 9.2 Professional suggested.
If you have a different Linux distribution (have a look at http://www.distrowatch.com/ for a good list of the different distributions available) then chances are that the installation instructions below will differ slightly for you.
The easy way
As the name suggests, this way is, well, easy. The problem with this way however, is that it will not work on all Linux distributions. If you have a look at the Mono download page (http://www.mono-project.com/downloads/index.html[^]) you will see that there are a packages available for some versions of the more common Linux distributions including Red Hat, SuSE, Fedora, and Novell Linux Desktop. Now a lot of Linux distributions will be compatible with some of these installation packages but specifying which ones are and which ones are not is well outside the scope of this introductory article. Unfortunately, if you are not using one of the listed distributions you'll have to either find out from your distributions documentation which of the packages are compatibly or you can download the Mono source and build Mono from that (covered in the Not for the faint hearted section below). If you are not familiar with Linux I would recommend trying your best to avoid the latter option as it can get messy.
So, you have a Linux distribution that the Mono download page seems to like. Great. You're in luck as this is going to be painless:
- On the Mono download page, click on the "Packages" link beside the Linux distribution that you believe to be compatible with your distribution. I simply selected the link beside SuSE 9.2
- This should bring you to a page which lists a lot of different packages that have been compiled and packaged for that particular Linux distribution.
- For the time being we are only interested in the "Mono Core Runtime and C# compiler" section in the top left.
- In this section you need to click on the download link for the Mono Core. The exact name will vary depending on the packages link that you selected but in general it will start with "mono-core-1.0.5". I used http://www.go-mono.com/archive/1.0.5/suse-92-i586/mono-core-1.0.5-1.ximian.10.4.i586.rpm
- Download this file and remember where you have saved it!
- When it has downloaded simply open the file and it will launch the package manager for your particular distribution.
- From this point on you'll have to follow the particular installation procedure for your package manager but in general there is simply an "Install Package" button. Click it!
- After a while, the Mono core should be installed. Congratulations
If you are inquisitive, bored, or if the above instructions didn't work for your distribution then the next section runs over how to build and install from the source. In general this should be a painless procedure but as you will see, it turned out to be less then painless with the default SuSE 9.2 Professional install that I decided to work from.
When you went to the packages page you probably noticed downloads for Gtk#, XSP and a number of other things that the Windows installer installed by default. For the time being you can ignore these. In future articles I will need you to have these packages installed but if and when the need arises, I will run through the installation process.
Not for the faint hearted
If you have Mono installed on your Linux distribution at this stage then you can skip ahead to the Your Mono toolset section. That is, of course, unless you are interested in finding out how I spent two hours getting the source to compile.
Ok. So you want to compile Mono from the source and then install it. No problem. This "should" be a simple process. I have configured, compiled and installed applications from the source code numerous times on Linux without problem. Not this time. In this section I'm going to explain to you how things "should" work from the source. I'll then show you how things worked for me when I configured, compiled and installed from Mono Source. Here goes:
- The first thing you need to do is download the source. Once again, head on over to the Mono download page at http://www.mono-project.com/downloads/index.html[^].
- In the source code section click on and download the Mono Runtime source (usually at the very top). The one I downloaded and worked off is http://www.go-mono.com/archive/1.0.5/mono-1.0.5.tar.gz.
- Once the file has been downloaded, go to a console for the remainder of the process.
- I would recommend performing the rest of the process as a user with root privileges. If you have just installed Linux as a standalone machine you can usually give your account root privileges by typing the
sudo bash command and entering the root password.
- You can decompress the downloaded file using the command
tar -xvzf mono-1.0.5.tar.gz where mono-1.0.5.tar.gz is the name of the file you downloaded.
- Next, switch to the directory where the source code has been decompressed too by typing
cd mono-1.0.5 or
cd followed by the name of the directory that you decompressed the file to if it is different from mine.
- Now, before we can compile the source you need to configure the make files. To do this simply type
./configure --prefix=/usr. This will take a bit of time. I am assuming here that there were no errors and that the
./configure --prefix=/usr went ahead without issue. As you will see from my experience, which I outline below, this was not the case for the default SuSE 9.2 Professional installation.
- When the the
./configure --prefix=/usr completes you are free to go ahead and compile and install the source.
- To actually compile the Mono Runtime source you need to run the
- Finally, to install, for lack of a better word, simply run the
make install command. This will deploy the compiled binaries, libraries and other bits and pieces to the correct directories.
Now, that is how things should work. And, if I had installed a version of SuSE 9.2 Professional with the development tools installed, then that is what would have happened. However, as I have mentioned before, I opted for the default installation. I wanted to see how things would be for somebody who was coming from Windows and was more accustomed to OS installs that require the minimum of configuration.
The following, rather long set of steps, is what I had to do to configure, compile and install the Mono Runtime source. It not that it is a complicated process. Everything is actually quite simple. It's just that it can be rather daunting to someone with very little Linux experience to see their initial
./configure --prefix=/usr fail when all the documentation for the Mono install tells them to do is type three commands:
./configure --prefix=/usr then
make and finally
make install. I was in two minds about whether I should add my experience with the Mono source as it is quite long and it might not add anything to the article. However, since I was having these issues I was sure that others would too and hopefully my experience can help you if you are faced with similar problems. Feel free to skip the rest of this section if you already have Mono installed.
So. Here's what I done, and all just for you!:
- Downloaded "Mono Runtime 1.0.5" from http://www.go-mono.com/archive/1.0.5/mono-1.0.5.tar.gz
- Decompressed the download and then moved into the source directory.
- Ran the
sudo bash command to give myself root privileges.
./configure --prefix=/usr for Mono.
./configure --prefix=/usr failed as default SuSE install does not have the needed compilers installed.
- Installed Compilers (gcc c++ and it's dependencies) using Yast.
./configure --prefix=/usr for Mono again.
./configure failed because the default install does not have bison installed.
- Downloaded bison from http://ftp.gnu.org/gnu/bison/bison-2.0.tar.gz.
- Decompressed bison download and moved into the decompressed directory.
./configure for bison.
./configure for bison failed because GNU m4 version 1.4 (or greater) is needed.
- Downloaded m4 from http://ftp.gnu.org/gnu/m4/m4-1.4.1.tar.gz.
- Decompressed m4 download and moved into the decompressed directory.
./configure for m4... Succeeded!
make for m4... Succeeded!
make install for m4... Succeeded!
./configure for bison, again... Succeeded!
make for bison... Succeeded!
make install for bison... Succeeded!
./configure --prefix=/usr for Mono for the third time.
./configure failed, again, because "pkg-config" is needed and is not installed by the default SuSE 9.2 install.
- Downloaded pkg-config from http://www.freedesktop.org/software/pkgconfig/releases/pkgconfig-0.15.0.tar.gz.
- Decompressed pkg-config download and moved into the decompressed directory.
./configure for pkg-config... Succeeded!
make for pkg-config... Succeeded!
make install for pkg-config... Succeeded!
./configure --prefix=/usr for Mono for the fourth time!
- Guess what?.. Yep..
./configure failed again. This time because glib-2.0 (or greater) was needed and was not installed by the default SuSE 9.2 install.
- Downloaded glib-2.6.1 from ftp://ftp.gtk.org/pub/gtk/v2.6/glib-2.6.1.tar.gz.
- Decompressed glib-2.6.1 download and moved into the decompressed directory.
./configure for glib-2.6.1
./configure for glib-2.6.1 failed because there was no "gettext" support in the C libraries installed in the system
- Downloaded gettext 0.14 from ftp://ftp.heanet.ie/mirrors/ftp.gnu.org/gnu/gnu/gettext/gettext-0.14.tar.gz.
- Decompressed gettext 0.14 download and moved into the decompressed directory.
./configure for gettext... Succeeded!
make for gettext...
make for gettext failed because there is not C# compiler installed! :wtf: :confused:...
make suggests installing Platform.NET :rolleyes:
- Reconfigured gettext as there was no way I was installing Platform.NET just so I could install Mono.
./configure --disable-csharp for gettext... Succeeded!
make for gettext, again... Succeeded!
make install for gettext... Succeeded!
./configure for glib-2.6.1 again... Succeeded!
make for glib-2.6.1... Succeeded!
make install for glib-2.6.1... Succeeded!
./configure --prefix=/usr for Mono for the fifth time... Succeeded! Finally!
make for Mono... Succeeded!
make install for Mono... Succeeded!
- Took a well earned breather.
The above set of steps that I had to go through to get the source compiled might seem a little daunting to some but to be perfectly honest it was an easy enough procedure. The main issue was the time taken. For example, the
./configure for Mono could take around 2 or 3 minutes each time. Each
./configure for the other items that had to be compiled and installed had similar time periods and generally speaking the
make command took longer than its accompanying
./configure. There was also the time spent looking for, downloading and decompressing the source files for the different items that needed to be installed. Oh, and I had to actually restart SuSE before I could use the installed tools.
Your Mono toolset
At this stage you've either given up or you're in for the long haul. Not that there is much left to do. We have Mono installed and the tools that we need to compile and run C# applications are ready to be used. Before we start to actually write and compile applications I thought it might be a good idea to have a quick overview of some of the tools the you should have available to you at this stage. I'm not going to go into any detail on the tools as in this article, and over the rest of this series, I will explain the details of the tools as they are needed.
|disco||Mono's Web Service Discovery Tool|
A tool for discovering web services and for retrieving the documents that describe those services.
|gacutil||Global Assembly Cache management utility|
A tool used by developers to install assemblies into the system Global Assembly Cache (GAC) to become part of the assemblies that are available for all applications at runtime.
|ilasm||Mono IL assembler|
The Mono IL assembler. Comparable to the Microsoft ilasm.exe tool.
|mcs||Mono Compiler Suite.|
The Mono C# compiler, an implementation of the ECMA-334 language specification. The compiler accepts all the same command line options that the Microsoft C# compiler (csc.exe) does.
A mono interpreter that allows for the execution of applications without using JIT. The instructions are interpreted directly into x86 instructions.
|mono||Mono's ECMA-CLI native code generator (Just-in-Time and Ahead-of-Time)|
A runtime implementation of the ECMA Common Language Infrastructure. This can be used to run ECMA and .NET applications.
|monodis||Mono assembly disassembler|
A tool that allows applications to be disassembled into IL. Provides similar functionality to Microsoft's ildasm.exe.
|monograph||Mono assembly information tool|
A tool that allows you to create call graph or type hierarchy information from assemblies.
|monop||Mono Class Outline Viewer|
A tool that allows you to view the outline of a class. You can see the signature of each member of the class.
|sn||Digitally sign/verify/compare strongname on CLR assemblies|
Digitally sign, verify or compare, CLR assemblies using strongnames.
|soapsuds||Mono's Remoting Proxy Generator|
A tool for generating WSDL documents and client proxies for remoting services.
|wsdl||Mono's Web Service Proxy Generator|
A tool for generating proxy classes that can be used to access to web services.
|xsd||Mono's utility for generating schema or class files|
A tool that is intended to complement the XML serialization support of Mono.
Remember, this is only a subset of the tools that are available. If you are interested in exactly what tools are available you should have a look on the Mono homepage.
Also, when using Mono on Windows it would be a good idea to add the <Mono_Install_Dir>\bin\ and <Mono_Install_Dir>\lib\ directories to your path (C:\Program Files\Mono-1.0.5\bin\ and C:\Program Files\Mono-1.0.5\lib\ on my system). This will allow you to use the above tools directly from the command line regardless of which directory you are currently working in.
About time! To get to this point should not have taken you all that long, unless of course you ended up installing Mono on Linux from source and ran into the trouble that I did. So let's get on with it.
The proverbial "Hello World!". You've no doubt seen a hello world application in C#, or other languages, numerous times in the past and you are once again going to see it. It's kind of a tradition and who am I go against tradition?
Anyway, fire up your favorite text editor, be it notepad on windows or joe on Linux. Type in the code below, or even easier, copy it from the article and paste it in.
public class HelloWorld
public static void Main(string args)
Save this as HelloWorld.cs and get ready to witness the wonders of Mono. To compile this application simply go to the command line and type
mcs HelloWorld.cs and hit enter. Note that the previous command assumes that your command prompt is working in the same directory as the HelloWorld.cs file and that the Mono directories have been added to your path if you are using Windows. If all goes well you should be presented with the "Compilation succeeded" text. Congratulations. You've just compiled your first C# application on Mono.
To execute the application using Mono simply type
mono HelloWorld.exe and hit enter. You'll be greeted by the text "Hello World". What you have done here is loaded the Mono JIT Runtime which JIT compiled the IL code inside the HelloWorld.exe assembly and executed the instructions. You could have also executed the application by running
mint HelloWorld.exe. This would have used the Mono Interpreter to convert all the IL of the application directly to x86 instructions before executing. This is similar to using the ngen.exe application with .NET.
If you are running Mono on Windows you may have noticed that you can also execute the application by simply double clicking on it. You may not see this as being special in any way but what you have done is taken an application created with the Mono C# compiler and executing it on the Microsoft .NET Runtime. More about this below in the .NET and Mono interoperability section.
Something a little more complicated
Hello World is the traditional first program, but in all honesty it doesn't really do much. The next example is a bit contrived but it shows a few more of the features of Mono including the
System.Text.RegularExpressions namespaces. I also know that the code is all lumped into the
Main method and that it should be refactored but as I said, this is just a contrived example, and not a lesson in code style.
The example simply takes a string that you want to search on http://www.google.com/ for and then displays the first five results that comes back. Nothing major but it does show an ever so slightly more complicated example than the Hello World example above. Anyway, once again, fire up your favorite text editor, type in the code below or copy it from the article and paste it in.
static void Main(string args)
Console.Write("Please enter string to search google for: ");
string searchString = HttpUtility.UrlEncode(Console.ReadLine());
WebClient webClient = new WebClient();
byte response =
string regex = "g><a\\shref=\"?(?<URL>[^\">]*)[^>]*>(?<Name>[^<]*)";
= Regex.Matches(Encoding.ASCII.GetString(response), regex);
Console.WriteLine("===== Results =====");
if(matches.Count > 0)
foreach(Match match in matches)
" - " + match.Groups["URL"].Value);
Console.WriteLine("0 results found");
Save this file as GoogleExample.cs and go back to the command line. The command to compile this application is a little different to the one we used for the Hello World example. This application makes use of the
HttpUtility class which is defined in the System.Web.dll assembly. That means we need to reference this assembly when compiling. To do this you simply use the
-r switch. This is the full command you need to type to get this application to compile:
mcs GoogleExample.cs -r System.Web.dll
Once again, the previous command assumes that your command prompt is working in the same directory as the GoogleExample.cs file and that the Mono directories have been added to your path if you are using Windows.
As with the Hello World example you can run this application from the command line using
mono GoogleExample.exe or
mint GoogleExample.exe - Take your pick. The same compiled assembly will run on Windows and Linux. You can test this by compiling it on Windows, copying the assembly to a Linux machine and running the
mono GoogleExample.exe command there.
.NET and Mono interoperability
I mentioned in the Hello World example above that you can simply take the assembly created by the Mono compiler (HelloWorld.exe in that example), double click on it in a Windows environment with .NET installed, and it would execute. How exactly does that work? Well, it's simple really. The Mono C# compiler, and the Microsoft C# compiler, compile code into an intermediary form known as IL. When you execute an assembly the runtime interprets and executes the IL code. So you can take an assembly compiled from VB.NET code, or any .NET language, and run it on Mono and vice versa. There is however one small issue with this; Mono doesn't have a complete implementation of the .NET class libraries so not all of your applications can be run using Mono. Don't worry too much about that now as over the next few articles in this series we'll see what can and can't run and hopefully examine why.
Hopefully this article has shown you how to install Mono and get your first Mono applications up and running on Windows and on Linux. That's not all that much though. You'll obviously want to do more than just create simple console applications. As I've said throughout this article, this is just the first in a series of articles that I'll be writing about Mono and Cross Platform .NET development using Mono. So, what's on the cards for the next article? Well, I know it would probably be best to jump in a start creating cross platform GUI apps but before we look at this I want to do an introduction to Web Application and ASP.NET development using Mono, which is what the next article will be about; writing your first ASP.NET application that runs on both Linux and Windows.
June 8th, 2005 - Corrected details about Mono tool "mint".
March 1st, 2005 - Updated some language mistakes and changed to install Mono in the /usr directory when installing from source on Linux.
January 25th, 2005 - First Posted.