Command Line Junkie

The original subject behind this month's article, was going to be "Cross Platform C#", however, during the course of sketching it out, I realized that there wasn't really enough material to do the actual article I wanted to do.

You see, last time I actually had to port any C# code to a system other than Windows, was quite some time ago.

In fact it was so long ago, that Mono was still quite in its infancy and .NET 3.5 had only just arrived on our doorsteps.

Armed with what I knew from then, and going forward into now, I made some assumptions that turned out to be wholly incorrect.

Back then, when I first tried doing some cross platform code, the only thing I actually had any real success porting across was simple command line programs, using standard output and standard input for their I/O.

For the younger members of the audience standard input and standard output - aka stdin/stdout are what you use when you're at a command prompt or in a power-shell session, in the days before Windows and on most servers this is still the only way to work.

This wasn't really a problem though, because in all honesty, the code I was porting across was simple 'CGI' (CGI = Common gateway interface) binaries anyway, so it wasn't a big deal.

I did as part of learning Mono however, attempt to write some simple win-forms programs, and quickly discovered many differences in the naming of objects and namespaces, that where very different to what I was used to on the Windows platform.

So back to the point of this article, when I sat down to write this, I did a few tests first, just to see if I still had the same environment that I had back then, and was very surprised to find that I didn't.

You see I'd intended to document these changes, and give folks a point by point trouble shooting guide, but the ONLY problem I actually encountered was trying to run a win-forms program at an SSH terminal command line (more on that soon).

So the question now remained, what to do?  Scrap this idea, and run with the next one, or see what I could salvage?  Well as you may have guessed, I opted for the later of the two.

So what has 'Cross platform' got to do with being 'A command line junkie', well everything really if you think about it.  You see, many people who use Visual Studio and other tools don't often realize, that you don't actually need Visual Studio to write .NET applications at all, and everything we’re about to do here, we're going to do using a command line.

When you install .NET on your Windows PC (even just so you can run a .NET application) , you are in actual fact installing all the compilers, linkers and other tools you actually need (and use) when building your applications.

Don't believe me?

Take a look in:




You should see a number of folders matching each version of .NET you have installed, and if you go into one of them, in most cases you'll see tools such as 'csc.exe' & 'vbc.exe'

You may also see 'msbuild.exe'. Msbuild is the tool used by Visual Studio to compile your project files, which are just msbuild scripts, and most of the time if your rebuilding an app or solution you only need to go to the folder where your project lives and type:

msbuild <solutionfile.sln>

To Actually Compile and Build Your Project 

If you do actually try this, you'll see the output is identical to what you see in the output pane when working in the Visual Studio editor.

This article however, is not about msbuild (I may cover that in a future article); what we are going to look at here is 'csc.exe'

CSC is the 'C Sharp Command-line' compiler and as you may have guessed is used to compile generic C# code there and then without the complexities of VS, and for those who are wondering, VBC is the visual basic compiler.

Before we go any further, you might want to make sure that CSC is in your path, that way you can call it simply by just specifying 'csc' instead of 'c:\windows\Microsoft.NET\version\csc.exe' each time you want to use it.  From now on, I'll just be referring to it as 'csc'.

Fire up notepad or some other simple text editor and create a file called 'cmdline.cs'. Enter the following c# code into this text file:

using System;
namespace dnnutsandbolts
  static class cmdline
    static void Main()
       Console.WriteLine("Hello World!");

Now open up a command line in the folder where you just saved it, and type:

csc cmdline.cs


If everything worked ok, you should now have a 'cmdline.exe' program.  Go ahead, run it by typing 'cmdline'; you'll see that it works exactly as expected and displays 'Hello World' on the command prompt.

If you ever need to hack together quick and dirty command line tools, this is the way to do it.  I've done this millions of times to add extra tools needed in batch files and other scenarios.

You may not realize it, but you've just done pretty much what creating a new console mode application project does in visual studio, only much quicker and quite a bit easier I'm willing to bet.

Time to Try Something a Little More Involved

Create a new file called 'winform.cs' and enter the following code:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace dnnutsandbolts5
  static class winform
    static void Main()
      Application.Run(new HelloWorld());

  public class HelloWorld : Form
    public HelloWorld ()
      Text = "Hello world";

      Button b = new Button {Text = "Click Me!"};
      b.Click += Button_Click;
      Controls.Add (b);

    private void Button_Click (object sender, EventArgs e)
      MessageBox.Show ("Button Clicked!");

And just as before from your command line enter:

csc winform.cs

Which should result in 'winform.exe' appearing in the folder; and like the previous example, typing 'winform' and pressing return, should run your app and present a simple form, with a clickable button on.

OK, so this is great, and potentially quite useful, but what's it got to do with Linux and Mono?

Well now that you know you can create programs in C#, using nothing more than a simple editor and a command line, how about we try opening up a Linux command line and see if we can do the same?

How you do this is entirely up to you and what you have available.  For me, I have physical servers that I have access to via an SSH command line, using Putty.  For the winforms test I created a virtual machine using virtual box, then installed a desktop version of Ubuntu on it.

Once you can get your command line open, copy your 'cmdline.cs' file across to your Linux box by whatever means you have.

Once you've copied, switch to the folder where you created it, and type the following:

gmcs cmdline.cs

At this point, I am assuming you have the Mono development system installed on your Linux system; if not then for me under Ubuntu server, it was simply a matter of typing:

sudo apt-get install mono-complete

If you’re using a different Linux please refer to your system documentation for the correct process.

'gmcs' is to Mono what 'csc' is to .NET on windows, it's the C Sharp compiler frontend and is targeted specifically at version 4 of the .NET runtime.  There is also 'mcs' which will create output for .NET version 2 runtime or for projects targeting V3.5 or lower.

If 'gmcs' worked above, then just as with Windows, you should have a 'cmdline.exe' application, ready to run, and if you run it, you should get 'Hello world' just as before.

You can also, compile your winforms app in the same way:

gmcs winform.cs -r:System.Windows.Forms.dll -r:System.Drawing.dll

There is you'll notice, one difference.  Unlike 'csc' your usings are not picked up automatically so you generally have to specify them using the '-r' syntax shown above, it's for reasons like this you’re advised to use a build runner.

If you try running the winforms app in a command only environment, you'll get an unhandled exception that makes no sense.  It took me about an hour of digging to realize it was because the Linux box I was using did not have any GUI/Desktop software installed on it. Something that kind of makes sense, if you’re building graphical software.

Installing a Desktop Linux (as previously described) and making sure that Mono was installed, then compiling and running, allowed me to take the exact same source code from Windows across to Linux, and compile it without making any changes however.

The ultimate question then, is why is this useful, and where do I go from here.

Well it's useful, because in recent months, as more and more companies start to embrace Open Source software, many businesses are moving to Linux based platforms to cut down on licensing costs. As a result, many are also porting across huge enterprise projects, originally written using Microsoft Tools for the Windows platform, and so starting a whole new business of porting software across.

I can almost hear everybody reading this, thinking… Can I run my 'MVC site' on Mono, and what about webforms? The answer to both of those questions is yes, if you're running under the Apache web server, then you can simply install 'mod_mono' and give Apache everything it needs. You will have to make some minor changes here and there, and I think the webforms implementation is only good to about 3.5 at present.  As always though, the documentation and source code is your friend.

Another thing to be watching, is the upcoming 'OWIN' standard, for the open Windows hosting platform. We already have many self-hosting tools, as well as tools to host OWIN apps on IIS, Apache, Nginx and many others.

If hosting under a web server is not your cup of tea, then you always have the option of using something like NancyFX (which I myself have tried with great success to provide Json Endpoints for a web application) or Service Stack.

If you look closely at many of the packages available in NuGet, you'll see a lot of them have been tested and are known to work on Mono.

That's all for this week, but in a future article we'll look at getting a full cross platform project up and running in either MVC or something similar.

If you have any ideas for anything you'd like to see in this column, then hunt me down on the interwebs.  I can generally be found hanging around Twitter as @shawty_ds or in the Linked.NET (Lidnug) users group on Linked-In that I help run.

Until next time, keep porting.

Related Articles


  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds