Wierd C# exception behaviour: exception not caught in special circumstances - c#

I'm programming a dll as extension for a program (Windows 10, Visual Studio Professional 2019). In this dll I have a very weird behaviour. The scenario:
From then 'main' module of the dll (where the callbacks for the application are located) I open a dialog window (own module) which is calling functions in a third module in it's 'Form Shown' event. In this third module I throw an exception (because the user cancelled an action) which I want to catch in the 'main' module.
When I run this dll in VisualStudio debugger (either Debug or Release Configuration, no difference), the Application is started, the dll is loaded and the process described above works like a charm.
When I run the application w/o VisualStudio, the Application is started, the dll is loaded but after throwing the exception it's not caught as before and I get told by the system that an exception was thrown and not caught.
So why does the code work in the IDE environment but not 'standalone'?
The only thing I could imagine was that there are differences in the event handling code of .NET. In the call stack when I stop in the 'Shown' event function, I see that there are calls to "mscorlib.dll!System.Threading.ExecutionContext". Is it possible that outside of VS the dll is in another execution context so that the exception is mislead?
I would appreciate if someone could explain me this behaviour. Again, it's not a matter of debug or release version, it's about the execution environment.
Thanks in advance,
Jörg
EDIT
I hope this clears the scenario:
dll.cs:
// This function is called from the host application
void callback()
{
try
{
Form dialog = new Form();
dialog.ShowDialog();
}
catch (ExceptionType1)
{
...
}
catch (ExceptionType2)
{
...
}
catch
{
...
}
}
dialog.cs
...
// event function for the 'shown' event of Form class
private void SynchronizationDialog_Shown(object sender, EventArgs e)
{
HelperFunction();
}
...
helper.cs
// here the exception is thrown
void HelperFunction()
{
...
if(...)
{
throw new ExceptionType1();
}
...
}
When debugging the dll in VS, the exception thrown in helper.cs is caught by the catch block, which is as expected.
When running the application calling the dll standalone, the exception is not caught.
EDIT
I now can provide an example project (VS2020): ExceptionCatchTest
If you run it in VS, Exception got caught, else not.

I created a test project using your code and was able to reproduce your problem. Looking through the exception's stack trace it seems the windows message processor Control.WndProc for the form is only in the stack while running from visual studio. As a test, I overrode the WndProc method in the form to add a try-catch block around the call to the base method
protected override void WndProc(ref Message m)
{
try
{
base.WndProc(ref m);
}
catch
{
MessageBox.Show("WndProc caught");
throw;
}
}
when running from Visual Studio, a message box appears indicating "WndProc caught". When not running in Visual Studio, this message never appears before the program crashes.
Thinking about it, probably the best solution to your problem would be to instead add a publicly visible enumeration such as public ErrorStatus errorStatus = ErrorStatus.NoError;. Then, instead of throwing and exception, you could use the following code
errorStatus = ErrorStatus.Error1;
DialogResult = DialogResult.Abort;
return;
You could then change your calling function to
void callback()
{
using (Form dialog = new Form())
{
DialogResult result = dialog.ShowDialog();
if (result == DialogResult.Abort)
{
switch (dialog.errorStatus)
{
case ErrorStatus.Error1:
...
break;
case ErrorStatus.Error2:
...
break;
}
}
}
}

Related

Exception Handler works only when run from within Visual Studio

I'm creating a Windows Forms application using Visual Studio 2012, C#, .NET 4.5; Windows 7.
I would like to handle any unhandled exception with my own error handler. I wrote some code like the own shown below. I even tried two different ways of error handling.
Now when I run this program within Visual Studio (2012), then this works very fine !
But when I start the program from explorer, then my error handler is never called; instead, there will always pop up the standard error handler from .NET Framework.
So what am I doing wrong?
static void Main()
{
try
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(HandleUnhandledException);
Application.Run(new frmMainFrame());
}
catch (Exception ex)
{
// Here is my error handler ....
}
}
static void HandleUnhandledException(object sender, UnhandledExceptionEventArgs args)
{
Exception ex = (Exception) args.ExceptionObject;
// Here is my error handler ....
}
Hook up Application.ThreadException as well.
Or set Application.SetUnhandledExceptionMode to UnhandledExceptionMode.ThrowException to have your appdomain handler kickin.
First at all i would use the Debugger.Break() Method to attach your program into to problematic code part. Than maybe just check if currentDomain is not null. Assumed that you don't raise a Exception that forces the CLI to stop.

How can I handle the exception which throws on an external dll?

I have developed a project which uses an external dll as FTPServer, I have created the FTP Server on my project like this:
private ClsFTPServer _ClsFTPServer;
_ClsFTPServer = new ClsFTPServer(FTPUserName, FTPPassword, FTPPath);
The Code above creates an instance of FTP server class, the class starts the FTPserver on it's constructor, it works fine independently as a module while the clients send their request correctly, but when an incorrect request comes to FTP server it throws an exception and cause my application to crash.
How can I handle the exception thrown by the external dll to prevent my application from crashing?
I recently answered a similar (ish) question which may prove useful -
Catch completely unexpected error
EDIT. I have to agree with Hans' comment above - might be an idea to find another FTP server.
Just for completeness, here's the appdomain/thread exception setup from - http://msdn.microsoft.com/en-GB/library/system.windows.forms.application.threadexception.aspx
Application.ThreadException += new ThreadExceptionEventHandler (ErrorHandlerForm.Form1_UIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
In case of using external unmanaged\unsafe code, .NET (above .net 4) by default cannot handle Memory Access Violation exceptions that happens inside of dll code.
in order to catch these kind of exceptions, there is three things to do. I did them and it worked for me:
Add these Attributes to the method that exception occurred inside of it :
(the method that calls the method of the unmanaged code.)
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
Add this tag to App.Config file below runtime tag :
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true"/>
<!-- other tags -->
</runtime>
Catch these kind of exception by using System.AccessViolationException exception type :
try{
//Method call that cause Memory Access violation Exeption
}
catch (System.AccessViolationException exception)
{
//Handle the exception here
}
What i said is just the cure for these type of exception. for more information about this exception's ego and how this approach works, see System.AccessViolationException
You've probably already tried this, but just in case, have you tried wrapping it in a try catch?
try
{
_ClsFTPServer = new ClsFTPServer(FTPUserName, FTPPassword, FTPPath);
...
}
catch(Exception e)
{
...
}
By putting a try...catch block around every call into the object and its methods.
Something like:
try
{
// use the DLL in some way
}
catch (Exception e)
{
// Handle the exception, maybe display a warning, log an event, etc.)
}
Also note that while running under Visual Studio, if you go to the "Debug" menu and select "Exceptions..." it will allow the debugger to break on ALL exceptions if you start your program under the debugger, and not just unhandled exceptions. Just click the 'Thrown' checkbox next to "Common Language Runtime Exceptions".

Getting exception that caused program to crash without being in debug mode

I have an application in C# that I want to run by just running the .exe from my desktop. However, I'm pretty sure there will be some type of error that will make the program crash. Is there a way to write the problem that caused the program to crash to a text file, so that I can see what caused the issue when users are using the program? I know I can use debug mode to do this but I want to run the application as a stand alone not inside of VS.
Thanks,
I am aware of the try catch blocks and I am already using those where problems might occur. But I am speaking in general. For example if I wasn't sure where the problem would occur. There is no way to print this specific error to a file.
You can try the global try/catch method except that if there is an exception on a background thread it won't be caught. You can use AppDomain.UnhandledException if you want to be notified of any unhandled exception in the appdomain (msdn). You would signup in main before the rest of your program executes like so:
static void Main(string[] args)
{
AppDomain.UnhandledException += WriteUnhandledExceptionToFile;
// rest of program
}
static void WriteUnhandledExceptionToFile(object sender, UnhandledExceptionEventArgs args)
{
// write to where ever you can get it.
string path = Path.Combine(Environment.CurrentDirectory, "UnhandledException.txt");
File.WriteAllText(path, args.ExceptionObject.ToString()); // will print message and full stack trace.
}
Edit
Note that by default Windows Forms and WPF catch any exceptions that are thrown on the UI thread. You will have to subscribe to the Application.ThreadException event (forms) or Application.DispatcherUnhandledException event (wpf) to be notified of exceptions on those threads. The code would be very similar to the code above for the AppDomain event.
Have a global exception handler that writes the exception details to a file.
If you wrap the code in your Main method in a try{}catch{} block, you can write out the exception details in the catch block.
try
{
// Calls to application code
}
catch(Exception ex)
{
// log `ex.ToString()`
throw; // rethrow to ensure termination optionally: `Application.Exit`
}
Even if you aren't logging the problem, you can usually get the error in question from the event viewer within windows.
The first thing you want to look at is the try/catch construct in C#. This is probably your first building block to handling errors.
As for how you handle the errors, that's entirely up to you. Currently your only stated goal is to log them to a file. You can get a lot of details out of the Exception object that you catch and you can write those details to a file. Additionally, you can use logging libraries to help with that sort of thing.
Proper error handling is something of a big subject, really. One thing to keep in mind is logically where you want to catch the exception. Ideally, you want to catch it where you can handle it. That is, where your code can sufficiently recover from the error. If it's a fatal error and the application should stop entirely, then you can throw the exception further up the stack and let it go unhandled (though still logged where you caught it).
If, however, you're in a logical condition where you can just log the error and move on, then the catch block allows you to do just that. Log the details, update the state of any objects/data which need to be updated, and continue with the flow of the application.
you can surround your one of the starting method with try catch block
try
{
///Your code
}
catch(Exception exception)
{
System.IO.File.WriteAllLines("ErrLog.txt", exception.Message);
}
As a permanent solution you can create extension method ToLog and use it whenever you want.
public static void ToLog(this Exception Exception)
{
using (var file = File.AppendText("ErrorLog.txt"))
{
file.WriteLine(DateTime.Now + " : " + exception.Message);
}
}
You can use it in catch block like this
catch(Exception exception)
{
exception.ToLog();
}
See initial information here http://www.csharp-examples.net/catching-unhandled-exceptions/
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
}
The UnhandledException event handles uncaught exceptions thrown from the main UI thread. The ThreadException event handles uncaught exceptions thrown from non-UI threads.
I would replace the MessageBox with some actual logging (log4net or others). This would give you the ability to log out the errors to another server for distributed applications, file system for local users, event logs, options are fairly unlimited if you're willing to put in the time.

How can I get WinForms to stop silently ignoring unhandled exceptions?

This is getting extremely irritating. Right now I have a winforms application, and things were not working right, but no exceptions were being thrown as far as I could tell. After stepping through almost all pieces of relevant code, it turns out that an exception was being thrown at the start of my application.
Long story short, in WinForms, being as awesome as it is, if an exception occurs the WinForms library ignores it. No "an unhandled exception has occurred" JIT message is thrown, it just stops processing the current event and goes back to the GUI.
This is causing random bugs, because code to load data isn't being called due to the exception occurring prior to this data being loaded.
To see this in action I created a brand new WinForms application, and entered the following code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string blah = null;
blah.Trim();
}
}
Press F5 and the form loads without any errors showing, even though a null reference is being thrown.
I then tried to go to my Program.cs main method and add Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); to it. Still my form loads without causing any errors to be thrown.
Even though I know that I can tell VS to break on all exceptions, I find this situation really bad. It causes really wierd issues that are hard to debug in production, and as this is an internal tool I really want to have it so it actually errors out when an exception occurs, and not silently disregards it.
Does anyone know how to do this?
Update: Just to update on things I have learned from the comments.
This does appear to be a 64-bit issue with windows, as I learned from this question which I did not see before posting. In that question it pointed to a Microsoft bug report about this, which had this to say:
Hello,
This bug was closed as "External" because this behavior results from how x64 version of Windows handle exceptions. When a user mode exception crosses a kernel transition, x64 versions of Windows do not allow the exception to propagate. Therefore attached debuggers are unaware of the fact that an exception occured resulting in the debugger failing to break on the unhandled exception.
Unfortunately where is nothing that the Visual Studo team can do to address this, it is the result of operating system design. All feedback regarding this issue should be addressed to the Windows team; however the Windows team considers this to be the "correct" operating system design, and considers the x86 behavior to be "incorrect".
Best Regards,
Visual Studio Debugger
That being said, builds not run through visual studio (or using Ctrl+F5 to run) does seem to show the JIT exception message box EXCEPT if you have the following code in your Program.cs:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
That code will cause windows to ignore the exception.
However, if you (instead) subscribe to the Application.ThreadException event, not only will your exceptions be caught, visual studio's debugger will break on unhandled exceptions!
In your Program.cs' Main function you should also ensure that you've wrapped your call to open the form in a try/catch. Additionally use the AppDomain.UnhandledException to catch exceptions. We also add Application.ThreadException too.
I believe the following will give you hooks into all the exceptions that can be thrown...
static void Main()
{
try
{
System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
System.Windows.Forms.Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(OnGuiUnhandedException);
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
var form = new MainForm();
form.ShowDialog();
}
catch (Exception e)
{
HandleUnhandledException(e);
}
finally
{
// Do stuff
}
}
private static void HandleUnhandledException(Object o)
{
// TODO: Log it!
Exception e = o as Exception;
if (e != null)
{
}
}
private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs e)
{
HandleUnhandledException(e.ExceptionObject);
}
private static void OnGuiUnhandedException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
HandleUnhandledException(e.Exception);
}
Try the following.
Handle exceptions in your main application entry point.
Also, manage unhandled thread exceptions using a ThreadExceptionEventHandler
This is the code snippet:
[STAThread]
public static void Main(string[] args)
{
try
{
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
//your program entry point
}
catch (Exception ex)
{
//manage also these exceptions
}
}
private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
ProcessException(e.Exception);
}
An easy fix is not to run under the debugger.
The debugger is masking the exception for some reason. If you run your app normally (Ctrl+F5), you'll get the usual "Unhandled exception has occurred in your application... Continue/Quit?" dialog.
Having experienced this often and identified the issue regarding 64 bit OS and the Form.Load event, I always just make a point of doing all my start up functions in the Form.Shown event. For all practical purposes this is the same thing (aside from a few rare, exceptional circumstances), and the JIT message is produced in the Shown event.

Why is Method.Invoke generating unhandled exceptions? Unable to catch even with TargetInvocationException

I'm trying to use Method.Invoke to call a windows form dialog, have a user perform some selections/interaction and continue execution. This invoke call is happening in an asynchronous method.
While everything works fine, should an error occur on the windows form, an unhandled exception is thrown, even when trying to catch TargetInvocationException or just Exception.
Both forms are in the same winforms project. I realize where are other ways to perform an async call but this is just to illustrate the issue.
The form dialog is as follows:
public partial class FakeDialog : Form
{
public FakeDialog()
{
InitializeComponent();
}
private void btnOK_Click(object sender, EventArgs e)
{
throw new Exception("oh noes!");
this.DialogResult = DialogResult.OK;
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
public new DialogResult ShowDialog()
{
base.ShowDialog();
return this.DialogResult;
}
}
And here is the calling code. None if the catch blocks are being executed, even when not debugging (my problem is not debugging exceptions in the IDE as mentioned here. The following results in an unhandled exception).
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
MethodInvoker simpleDelegate = new MethodInvoker(InvokeForm);
IAsyncResult tag = simpleDelegate.BeginInvoke(null, null);
simpleDelegate.EndInvoke(tag);
MessageBox.Show("All done");
}
private void InvokeForm()
{
try
{
Type t = typeof(FakeDialog);
MethodInfo showDialogMethod = t.GetMethod("ShowDialog", new Type[] { });
object dialog = Activator.CreateInstance(t);
System.Windows.Forms.DialogResult result = (System.Windows.Forms.DialogResult)showDialogMethod.Invoke(dialog, new object[] { });
MessageBox.Show(result.ToString());
}
catch (TargetInvocationException tie)
{
MessageBox.Show("Tie exception");
}
catch (Exception ex)
{
MessageBox.Show("general exception");
}
}
}
UPDATE:
Strangely, I'm able to catch the exception when running with debugging (I'm sure the IDE is helping here). Running without debugging causes the unhandled exception.
Also, invoking via an async call doesnt seem to make a difference. If i just call InvokeForm() (ignore all the methodInvoker stuff), I can achieve the same result.
Operating on .NET 2.0 using Visual Studio 2008.
Ok, figured it out.
The result from the code was unhandled exceptions. And while using Method.Invoke for a simple method in another class would behave correctly, the environment changes with the source of the exception occurring in a form. A form event. And I eventually found on Microsoft Support that unhandled exceptions in Windows Form events are not propagated up call stack. There's some pretty interesting reasons for this ("Windows Forms applications have a top-level exception handler that allows the program to continue to run if it can recover").
It also gives credence to what Marc mentioned over putting things in the Load event. Sigh. So the reason for all this is pretty obvious now.
As for the code running fine while debugging (as opposed to without), I think I can thank the JIT debugger for that. #fluf pointed to me that specifically enabling the JIT debugger gave the same result as running with debugging. #Marc Gravell, depending on VS settings this might explain only I and fluf could reproduce. There's some more info on it here but it's not a production fix.
So the real solution is either handling the exceptions in the event handlers themselves or use the solution as mentioned in the Microsoft Support article above, which solves my issues.
I can't actually repro from your code, but: the Load event is.... different, and some odd things can happen if you get an exception inside the Load event. Simply my advice would be: move this code out of the Load event. It also doesn't help that attaching a debugger here changes the behaviour (a Heisenbug).
Without seeing MethodInvoker's declaration i can only guess, but it is possible that InvokeForm() method is executed on non-UI thread.
MethodInvoker simpleDelegate = new MethodInvoker(InvokeForm);
IAsyncResult tag = simpleDelegate.BeginInvoke(null, null);
To show a dialog you may consider to rewrite this as follows:
Action simpleDelegate = new Action(InvokeForm);
this.BeginInvoke(simpleDelegate);

Categories

Resources