tags:

views:

1305

answers:

3

If you try to launch a .NET 3.5 application on a Windows computer which does not have this version of the .NET framework installed, you get a FileNotFoundException for some system assemblies (for example System.Core 3.5.0.0).

Is it possible to catch this exception and tell the user to upgrade their .NET framework or is it thrown too early to handle it?

+3  A: 

The simplest thing would just be to try it. (I don't have any non-3.5 machines to test it on, but I assume you do.)

Make your entry point a very simple one which just tries to load System.Core.dll and handles the exception appropriately. If it passes, move on to another class which can then use it. If it fails, give the appropriate error message and exit.

I suspect you don't need to have quite this level of isolation - so long as you don't have any fields which are of unavailable types, I wouldn't expect the assembly to be resolved until you first call a method which needs it. I'd have to consult CLR via C# to check. However, keeping it quite isolated would probably be safer - it avoids you accidentally introducing dependencies later. Heck, you could even have your "boot and check" type in a separate assembly which did nothing but launch another one if everything's okay.

Jon Skeet
+2  A: 

You can catch that exception, yes.

In your main routine, just use a try..catch around your main message loop.

try
{
   Application.Run(new MainForm());
}
catch (Exception ex)
{ 
    if (ex.MessageContains("Could not load file or assembly 'System.Core, Version=3.5.0.0"))
    {
        MessageBox.Show("This product requires the Microsoft .NET Framework version 3.5, or greater, in order to run.\n\nPlease contact your System Administrator for more information.");
    }
}
Ch00k
+3  A: 

How are you currently deploying the app? ClickOnce can do assembly (GAC) checks before launch, and with msi you should have a whole range of pre-check options available... although not always feasible, you might consider one of these deployment options?

Re catching the exception - just be sure to split the Main up so that it does nothing except catch the exception - otherwise JIT can stop your Main from loading:

// [STAThread] here if winform
[MethodImpl(MethodImplOptions.NoInlining)]
static void Main() {
    try {
       MainCore();
    } catch (SomeException ex) {
       // TODO something simple but fun
    }
}

static void MainCore() { ... } // your app here...

If you put too much in the outer Main, it can barf before running any of it, since JIT might need the types.

Marc Gravell
dude, you just provided the solution to something I've been working on all morning, you saved me hours of banging my head against the wall. thanks!
Epaga
[MethodImpl(MethodImplOptions.NoInlining)] should be on MainCore here, shouldn't it?
Dave Cluderay
@Dave - quite possibly; it was nearly 2 years ago, so my memory is hazy, but what you say makes sense.
Marc Gravell