couple weeks ago, my friend and co-worker, shani raba, presented me a problem.
they have some sealed application as an .exe file that throws some exceptions and crashes their application.
So, i Thought that is a good idea to wrap the targeted application with reflection, and catch the unhandled thrown exceptions.
to demonstrate this,
I've created an application with a button that throws an exception.
private void button1_Click(object sender, System.EventArgs e)
{
throw new Exception("my Exception, need to be wrapped");
}
the next thing that we need to create is the wrapper.
so, creating a console application with this code should have solved the problem:
[STAThread]
static void Main(string[] args)
{
Assembly assembly = Assembly.LoadFrom ("cashTester.exe");
Type t = assembly.GetType("cashTester.Form1");
object o = Activator.CreateInstance(t);
try
{
Application.Run((Form)o);
}
catch(Exception ex)
{
Console.Write("exception was thrown : " + ex.Message);
}
}
running this code in debug mode successfully catch the exception from the winform.
but, for some reason, in a normal run, this code won't catch the exception.
makes you wonder, huh ?
so i did some thinking, what on earth can make this phenomena ?
The answer is : Threads.
Yes, like it or not, but this is the subject that everyone tries to avoid it.
everyone knows it exists, and no one really likes it,
but we can't run from the problem, we need to confront it.
So, what can we do ?
since Application.Run launches a new thread, we can add to the Application.ThreadException event handler, an exception handling method.
like this class :
/// <summary>
/// The Wrapper class
/// </summary>
public class Wrapper
{
/// <summary>
/// Public cunstructor
/// </summary>
public Wrapper()
{
}
/// <summary>
/// This function will initialize the exception handling
/// </summary>
public void Init()
{
// define handlers for unhandled exceptions
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(this.exp);
Application.ThreadException +=new System.Threading.ThreadExceptionEventHandler(this.ThreadExp);
}
/// <summary>
/// This method is for the threads exceptions
/// </summary>
/// <param name="o">the object</param>
/// <param name="args">Thread exception args</param>
void ThreadExp(object o, System.Threading.ThreadExceptionEventArgs args)
{
// Write the message to the console
Console.Write("Unhandled thread exception was thrown : " + args.Exception.Message);
}
/// <summary>
/// This method is for the unhandled exceptions from the main thread
/// </summary>
/// <param name="o">the object</param>
/// <param name="args">exception arguments</param>
void exp(object o,System.UnhandledExceptionEventArgs args)
{
// Write the message to the console
Console.Write("Unhandled exception was thrown : " + ((Exception)args.ExceptionObject).Message);
}
public void Run()
{
// Load the assembly
Assembly assembly = Assembly.LoadFrom ("cashTester.exe");
// get the type of the object
Type t = assembly.GetType("cashTester.Form1");
// invoke it
object o = Activator.CreateInstance(t);
// Run the application - note that this line starts an additional thread
Application.Run((Form)o);
}
}
now, all we need is to launch it :
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Wrapper w = new Wrapper();
w.Init();
w.Run();
}
now we got an exception wrapper for launching applications.
Shani, tell me if that helped ...
p.s.
There are more ways to do it, but this is the simplest one