The guys at the Mono Project have released their Mono Tools for Visual Studio. This must be one of the most anticipated projects of the year for me yet!

According to the official project page:

Mono Tools for Visual Studio is a commercial add-in for Microsoft™ Visual Studio™ that enables developers to write .NET applications for non-Windows platforms within their preferred development environment. It allows developers to build, debug and deploy .NET applications on Linux, while continuing to leverage the extensive ecosystem of code, libraries, and tools available for .NET.

While there’s a fair bit of marketing speak in there (I tune out pretty much whenever I hear the words “leverage” and “ecosystem”), the benefits are actually quite simple.

You can now remotely deploy and debug .NET applications on Mono directly from within Visual Studio!

I can’t begin to tell you how much help this is going to be in working on BlogEngine.NET on Linux. Unfortunately this capability isn’t open-source or free, but as a Visual Studio developer you’re probably going to be used to paying for features. Starting at $99 I guess it’s not too hefty a price to pay if you’re serious about using C# on Mono and Linux.

Here’s some of the awesome things you can do with it right now:

  • Directly deploy a .NET application to a remote Linux machine.
  • Debug and step through your code in Visual Studio as you run on a Linux box.
  • Built in portability checker for existing .NET applications.
  • Package your application as an .rpm for installation on distributions that support RPM’s (not Ubuntu unfortunately).

For more information, I’d suggest you go visit Miguel de Icaza’s blog, and also the official product page at the Mono project.

I’ll be following up this post shortly with a guide to getting it all to work on Ubuntu.

.NET Windows.Forms applications have a nasty habit of creating a lot of form flicker when doing form stuff like opening dialogs. This generally occurs when you have a long running operation (and I mean longer than a second) before opening a new form. This usually takes the shape of database access while retrieving values to display in your new dialog. Aside from that, there also isn't an easy built in way in Windows.Forms to show a wait cursor for the entire application while loading data.

The side effect of the flickering experienced by users is that your application appears to be slower than it actually is. It looks like your application hangs for a second or two to most users. I've even had users tell me that they can tell that the application is a .NET application because of the constant window flicker!

Clearly this kind of stigma is not something you want associated with your applications, so we'll explore a solution that not only takes care of the irritating flicker, but provides a reliable wait cursor across all forms in your application while you're busy loading data or doing other work.

The Hourglass class

Solving the wait cursor issue is easy thanks to a contribution by nobugz on the Microsoft Forums. Add the following class to your application:

    public class HourGlass : IDisposable {
        public HourGlass() {
            Enabled = true;
        }
        public void Dispose() {
            Enabled = false;
        }
        public static bool Enabled {
            get { return Application.UseWaitCursor; }
            set {
                if (value == Application.UseWaitCursor) return;
                Application.UseWaitCursor = value;
                Form f = Form.ActiveForm;
                if (f != null && f.Handle != null)   // Send WM_SETCURSOR
                    SendMessage(f.Handle, 0x20, f.Handle, (IntPtr)1);
            }
        }
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
    }

 

Using the HourGlass class is a breeze, all you have to do is wrap any time consuming code in a new HourGlass as follows:

        private void btnOk_Click(object sender, EventArgs e) {
            using (new HourGlass()) { 
                // do some work here
            }
        }

And that's all there is to having a wait cursor apply to your entire application while your main thread is busy working.

Solving the flickering

Thanks to the HourGlass class, solving the flicker becomes a breeze too. The flicker happens because your long running work occurs on the main application thread before your forms have had a chance to process their paint messages. This causes the form painting to be delayed until after your long running work has completed. This results in half painted forms being visible to the user, especially when doing something like closing a dialog box.

The solution is to force the form to process it's paint messages before starting your long running work. You can do this easily by calling this.Update() on the form that you're working in, but the discipline required to remember to do so can be an issue.

Luckily for us, the HourGlass class has given us a perfect opportunity to automate this call! See the updated hourglass class below:

    public class HourGlass : IDisposable {
        public HourGlass() {
            Enabled = true;
        }
        public void Dispose() {
            Enabled = false;
        }
        public static bool Enabled {
            get { return Application.UseWaitCursor; }
            set {
                if (value == Application.UseWaitCursor) return;
                Application.UseWaitCursor = value;
                Form f = Form.ActiveForm;
                if (f != null && f.Handle != null) {   
                    // force the form to process it's paint messages
                    // before performing any long running work
                    f.Update();
                    // Send WM_SETCURSOR
                    SendMessage(f.Handle, 0x20, f.Handle, (IntPtr)1);
                }
            }
        }
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
    }

We've inserted a call to Update() before sending the cursor message to the active form. This causes the active form to paint itself completely before changing cursors and before your long running work starts.

And there you go, suddenly your .NET Windows Forms application behaves just like every other well written Windows application!

Something that will come in handy while porting applications to Mono is the ability to detect whether an application is running under Mono or .NET, and also whether it's running on Unix or Windows. While one would hope that .NET applications would be completely binary portable, there are still some situations where Mono's infancy becomes a stumbling block.

From the Mono Project Technical FAQ:

Having code that depends on the underlying runtime is considered to be bad coding style, but sometimes such code is necessary to work around runtime bugs.

The following methods are documented in the FAQ, but to save everyone time, I'll document them here.

Detecting Mono:

 1: using System;
 2:  
 3: class Program {
 4:  static void Main ()
 5:  {
 6:  Type t = Type.GetType ("Mono.Runtime");
 7:  if (t != null)
 8:  Console.WriteLine ("You are running with the Mono VM");
 9:  else
 10:  Console.WriteLine ("You are running something else");
 11:  }
 12: }

Detecting Linux/Unix:

 1: using System;
 2:  
 3: class Program {
 4:  
 5:  static void Main ()
 6:  {
 7:  int p = (int) Environment.OSVersion.Platform;
 8:  if ((p == 4) || (p == 128)) {
 9:  Console.WriteLine ("Running on Unix");
 10:  } else {
 11:  Console.WriteLine ("NOT running on Unix");
 12:  }
 13:  }
 14: }

I apologize for the bad code formatting above, but I'm still fighting to get proper syntax highlighting working with Live Writer and BlogEngine.NET.


I am a software developer / architect currently interested in combining .NET technologies with open-source operating systems. 

I am a member of the open-source BlogEngine.NET development team and focus mainly on ensuring Mono compatibility for the project.

twitter

BlogEngine.NET


At StayUnlimited Cape Town accommodation we help you choose from and book guest houses, self catering apartments, bed & breakfasts, luxury villas and hotel accommodation.