.NET Framework Bookmark and Share   
 index > .NET Base Class Library > How to catch FileNotFoundException when missing one of referenced assemblies
 

How to catch FileNotFoundException when missing one of referenced assemblies

Hi all,

I'm developing asimple application that references an 3rd party assembly.
In case this assembly isn't installedin GAC, I want to display my custom errormessage and close the application.

My problem isthat FileNotFoundException is thrown before the Main function is called, so I can't handle this issue by the good way and windows Send/Don't Send dialog is displayed.

Is there any way to resolve this issue and programmatically close the application beforeFileNotFoundException is thrown?

Thanks,
Michael.

MishaSoft
>My problem isthat FileNotFoundException is thrown before the Main function is called

Just the fact that a referenced assembly is missing does not cause an application to crash immediately on startup. Typically, the error happens as soon as a method that makes use of the assembly is called.

If the problem is that the Main method is making use of the referenced assembly, you could try refactoring your Main method:

staticvoidMain()
{
try
{
OldMain();
}
catch(System.IO.FileNotFoundException)
{
MessageBox.Show("CaughtFileNotFoundException");
}
}

There are also the AppDomain.UnhandledException and Application.ThreadException events that are raised when unhandled exceptions occur. You might be able to use these events to gracefully shut down your application.
BinaryCoder
>My problem isthat FileNotFoundException is thrown before the Main function is called

Just the fact that a referenced assembly is missing does not cause an application to crash immediately on startup. Typically, the error happens as soon as a method that makes use of the assembly is called.

If the problem is that the Main method is making use of the referenced assembly, you could try refactoring your Main method:

staticvoidMain()
{
try
{
OldMain();
}
catch(System.IO.FileNotFoundException)
{
MessageBox.Show("CaughtFileNotFoundException");
}
}

There are also the AppDomain.UnhandledException and Application.ThreadException events that are raised when unhandled exceptions occur. You might be able to use these events to gracefully shut down your application.
BinaryCoder

Hi BinaryCoder,
Thanks for your reply.

This is my Main function:



using ExternalAssemblyNameSpace;
...........


static void Main(string[] args)
{

//Check Input Command Line Parameters
if (args.Length != 4)
{
MessageBox.Show("Error", "Error");
Environment.Exit(100);
}
}


I run my application without any command line params.
WhenI run this applicationwhile an referenced assembly is present in the same folder- I get the expected message.
When I remove referenced assembly from the folder - I get windows exception.
As could be seen from the code above, there is no any usage ofreferrenced assembly withing this code.

Is there any chance that "using" derective is the sorce for the problem?

  • Edited byMishaSoft Saturday, June 07, 2008 6:05 PMAn additional observation was made and updated in the post.
  •  
MishaSoft
BC is right, you won't get an exception until the JIT compiler tries to load the assembly to compile the code in its class methods. I cannot reproduce your problem. There must be something inside that assembly that somehow gets initialized at startup. No clue what that could be. Beware of static classes and field initializers. There must be a reason you didn't just remove the using statement...
Hans Passant.
nobugz
If you are not sure that the third-party assembly exists, you should do the following simple thing: do not ever referthe classesdirectly from that assembly. Here an explanation insamples:

tip #1:

replace the following code

class MyClass {
SomeTypeFromThirdPartyAssembly variableName;

void foo() {
variableName.DoSomething();
}
}

with this one

class MyClass {
object variableName;

void foo() {
try {
InternalFoo();
}
catch (FileNotFoundException) {
// Theruntime coulnd't find an assembly.
}

catch (TypeLoadException) {
// Theruntime coulnd't findreferencedtype inthe assembly.
}

}

private void InternalFoo() {
((SomeTypeFromThirdPartyAssembly)variableName).DoSomething();
}
}

First, the JIT compiler will not resolve the type referencesofclass members.
Second, the JIT compiler will not resolve variable references in 'foo' method.


tip #2:

When CLRcannot find an assembly it raises'AssemblyResolve' event onAppDomain class.
...
AppDomain
.CurrentDomain.AssemblyResolve += new ResolveEventHandler
(CurrentDomain_AssemblyResolve);
...
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs
args) {
//
args.Name -the name of the missing assembly.
return null
;
}


tip #3:

When an excpetion occurs in the main message loop of your forms application, and it's doesn't have any handlers, you can catch itby 'Application.ThreadException ' event:
...
void ThreadException(object sender, ThreadExceptionEventArgs e) {
// write a handler here
.....
// or throw it further
throw e.Exception;
}

But note, if the exception occurs in 'Application.Idle' event handler, it will not be catched and will not be handled with 'Application.ThreadException' event handler.


tip #4:

If you want totrack all unhandledexception in your program, you should advise'AppDomain.UnhandledException' event.
...
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledException);
...
void UnhandledException(object sender, UnhandledExceptionEventArgs
e) {

if
(e.ExceptionObject is ThreadAbortException)
// We shouldn't worry about threads being aborted, when some code calls 'Thread.Abort' mehtod,
// because runtime injects opcodeswith throwing this type of exception in the code.
return;

// log an exception here
......
// But be aware!, that the exception may come fromany thread.
// That means, this method is never synchronized with the main thread.

if (e.
IsTerminating) {
// This flag tells us whether the further program execution is impossible,
// andCLR will terminate the program. I.e. a criticalexception has occured.
}
}


That's all you should know,
Good luck :)

The most weird OX ever
Hi all,

Thanks to everyone for your assistnace, but it still doesn't work for me (including tip#1 provided byThe most weird OX ever)
I don't understand why you fail to reproduce the problem - it means that I have an additional problem on my side.

I reproduce the problem by following steps:

1. Created new Solution with Console Application (ConsoleApplication1).
2. Add to the same solution Class Library project.
3. Define strong-name signing for the ClassLibrary1 projects
3. The ClassLibrary1 project has the single class Class1:

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
namespaceClassLibrary1
{
publicclassClass1
{
publicstringGetMessage()
{
return"ThismessagewasreturnedbyClass1";
}
}
}

4. Add to the ConsoleApplication1 project reference to the ClassLibrary1 project output
5. Edit Program.cs file of the ConsoleApplication1 project as following:

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingClassLibrary1;
namespaceConsoleApplication1
{
classProgram
{
staticvoidMain(string[]args)
{
if(args.Length<2)
{
Console.WriteLine("HelloWorld");
Environment.Exit(0);
}
Class1cls=newClass1();
stringmsg=cls.GetMessage();
Console.WriteLine(msg);
}
}
}

6. Thats it.

Now, when I run ConsoleApplication1.exe while ClassLibrary1.dll is present in the same directory - every thing works as expected:
- When ConsoleApplication1.exe iscalled without any command prompt params - "Hello World" is displayed.
- When 2 command prompt params passed to ConsoleApplication.exe - "ThismessagewasreturnedbyClass1" is displayed.

But when I copy ConsoleApplication1.exe to an another folder, where ClassLibrary1.dll is missing, I get FileNotFound exception in the both cases (with command prompt params and without).
Following the exception details:

UnhandledException:System.IO.FileNotFoundException:Couldnotloadfileor____
embly'ClassLibrary1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=eca1358d5
898b7f7'oroneofitsdependencies.Thesystemcannotfindthefilespecified.
Filename:'ClassLibrary1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=eca1
358d5898b7f7'atConsoleApplication1.Program.Main(String[]args)

Any ideas?

Thanks,
Michael.




MishaSoft
You've ignored the advice given before in your repro code. What's the hang-up?
Hans Passant.
nobugz
Thanks to everyone for assistance,
I've foundthe problem out.

The main idea was to export the code, referring to types provided by external assembly,to the separate function.The call to this functionshould be enclosed within try...catch block.

If I understood correct, JIT compiles the whole function just a moment before it's called. So referring external types within the Main function throws exception when Main is being compiled (before any code starts to run).

I've mistakenly thought that exception should be thrown during the call itself, and not during function compilation.

Following working code:

staticvoidMain(string[]args)
{
if(args.Length<2)
{
Console.WriteLine("HelloWorld");
Environment.Exit(100);
}
try
{
InternalFoo();
}
catch(FileNotFoundException)
{
Console.WriteLine("Theruntimecoulnd'tfindanassembly.");
}
catch(TypeLoadException)
{
Console.WriteLine("Theruntimecoulnd'tfindreferencedtypeintheassembly.");
}
}
staticvoidInternalFoo()
{
ExternalTypevariableName=newExternalType();
Console.WriteLine(variableName.anyMethod());
}


Thanks,
Michael.
MishaSoft
I made the same mistaken assumption. Once I split the Main() in two, I was able to catch the exception.

Many Thanks! (I love Google) ;-)
allanclarke

You can use google to search for other answers

Custom Search

More Threads

• Generics related question.
• DirectoryInfo and GetDirectories classes
• SerialPort, C# frmwk 2.0 - Problem in RequestToSend
• Access admin pages through local host
• Reflection: Best way to identify if a specific Interface Exists
• General Operator System Name?
• DNA to .NET question
• Stripping diacriticals from string?
• Shared Memory between Multiple Instances of Application
• File Watcher class (.net framework 2.0)