Question

I have a windows 7 x64 desktop with vs2010 and a virtual box installation of linux with mono and monodevelop. I compile the following program with vs2010 and run it in the linux virtual machine and it fails with a seemingly uncatchable FileNotFoundException. If I compile it in the virtual machine and run it in windows, it works great.

The problem seems to be that an uncatchable exception is tossed by mono before Main() when it is impossible to load a dll. Is there a way to restructure my program or coerce mono such that I can catch this exception?

I am trying to write a single program that has an interface in either WPF or GTK according to what is available at runtime.

using System;  
#if __MonoCS__  
using Gtk;  
#else  
using System.Windows;  
#endif  
using System.IO;  
using System.Runtime.CompilerServices;  
using System.Collections.Generic;  

namespace Test {

 public static class Program {

  [STAThread]
  public static void Main() {
   try {
    Main2();
   } catch (FileNotFoundException e) {
    Console.WriteLine("Caught FileNotFoundException");
    Console.WriteLine("FileName = {0}", e.FileName);
   }
  }

  [MethodImpl(MethodImplOptions.NoInlining)]
  public static void Main2() {
#if __MonoCS__  
   Application.Init();  
#else  
   Window w = new Window();  
#endif  
  }

 }

}
Was it helpful?

Solution

You are exposing yourself to the implementation details of the JIT-compiler. The exact time it will throw the exception for the missing assembly depends on how eagerly it translates the IL into machine code. I know the Microsoft jitter is truly just-in-time, it compiles one method at a time, just before it is about to execute. Although this is affected by whether or not a debugger is attached. You're dead in the water if Mono, say, compiles the entire class. The jitter will throw before Main() can start.

Maybe it will work better if you put Main2() in another class. The best thing to do is just have an assembly available, a dummy if necessary.

OTHER TIPS

What DLL is not found? I'm assuming, judging from your code, it's probably WinForms. I'm not entirely familiar with the C# preprocessor, but I think #if __MonoCS__ may be more useful (or may act only) as a preprocessor define, that is, it doesn't change at runtime. You may try defining __MonoCS__ for the Mono build in the project settings and run that (I would think VS doesn't define that by default, so it's probably trying to work with WinForms anyway).

Another thing to try is commenting out the using System.Windows and all its related code (just using the GTK/Mono path) and test if that builds on Windows and runs on both. If so, then you've narrowed the possible problems down to just that include, and it should be easier to solve from there.

Instead of depending on the laziness of referenced assembly loading, I suggest you implement your platform-specific GUIs in different assemblies, perhaps implementing a common interface. The main assembly would then have no direct references to specific GUI toolkits, but would use reflection to try to load WPF or GTK from the GAC, and based on that would use reflection to load a specific GUI dll assembly and instantiate and use the GUI implementation.

Something like:

  • ProgramName.exe - contains Main entry point, IPlatformGui, and logic shared by all platforms
  • ProgramName.Gtk.dll - contains GtkGui : IPlatformGui
  • ProgramName.Wpf.dll - contains WpfGui : IPlatformGui
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top