I have a problem with my VSTO add in. On some random machines I recieve an AccessViolationException trying to use PropertyAccessor.GetProperty.
I couldn't find an explenation on the internet for why this exception accures.
Also it seems there is no way to catch this exception, i use a try catch block that catces (System.Exception), but it doesn't catch it and outlook crashes.
Any ideas on what can be the problem?
Decorate your method with the attribute
[HandleProcessCorruptedStateExceptions]:
[HandleProcessCorruptedStateExceptions]
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
try
{
//Do something...
}
catch (Exception ex)
{
//This is catching ALL exception types
//even AccessViolationException
//or OutOfMemoryException
}
}
Related
I can't figure out how to get the try catch to work. Need to have an error message box pop up when a non number is entered in the text boxes.
private void btnAdd_Click(object sender, EventArgs e)
{
int x = int.Parse(txtIn1.Text);
int y = int.Parse(txtIn2.Text);
txtIn1.Text = x.ToString();
txtIn2.Text = y.ToString();
lstOut.Items.Add((x + y).ToString("N0"));
try
{
int.Parse(txtIn1.Text);
int.Parse(txtIn2.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
With minimal modifications: move all the code into the try so it catches when any Exception is hit. You're encountering your exception outside of the try block. You are only going to ever see your catch triggered if something within the corresponding try block is throw an exception.
private void btnAdd_Click(object sender, EventArgs e) {
try {
int x = int.Parse(txtIn1.Text);
int y = int.Parse(txtIn2.Text);
txtIn1.Text = x.ToString();
txtIn2.Text = y.ToString();
lstOut.Items.Add((x + y).ToString("N0"));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
Edit: As suggested by commenters, I think this answer is incomplete without stating that a Try/Catch block is overkill in this instance.
A better approach would be to use the built-in TryParse method (which can return a boolean regarding the success of the parse attempt, and an output value). Here is one way you could accomplish this:
private void btnAdd_Click(object sender, EventArgs e) {
var xSuccess = int.TryParse(txtIn1.Text, out int x);
var ySuccess = int.TryParse(txtIn2.Text, out int y);
if(!xSuccess)
MessageBox.Show($"{x} could not be parsed to int!");
if(!ySuccess)
MessageBox.Show($"{y} could not be parsed to int!");
if(xSuccess && ySuccess)
lstOut.Items.Add((x + y).ToString("N0"));
}
You shouldn't use try-catch as a control block as explained in this SO post. Use if for that. Try catch is really meant to be used when you can't do otherwise or when something that you didn't expect happened.
You can use this SO post as an example and your code could look like this
private void btnAdd_Click(object sender, EventArgs e)
{
int x;
int y;
if(!int.TryParse(txtIn1.Text, out x) || !int.TryParse(txtIn2.Text, out y))
MessageBox.Show("Parse failed !");
}
You can use
Console.WriteLine(x);
Console.WriteLine(y);
to verify that the vars were properly given a value
For more information about the int.TryParse() method vs int.Parse() see this post
As other have mentioned, it's the first int.Parse() functions that are tripping things up - the ones outside the Try/Catch block.
I wanted to expand on the TryParse() function - and why should probably be using that.
Exceptions are expensive - they're a rather large overhead in terms of Time/CPU/etc. They're also not user-friendly. You want to say "Please enter a valid number" to the user, not "An exception occurred: ..."
Instead, you can use TryParse, which returns whether the parsing worked; the output of the parse is an "out" parameter in the inputs list:
int myValue;
bool parseWorked = int.TryParse("3", out myValue);
This doesn't have the Exception overhead - it runs quickly, regardless of whether the input's valid.
Why not use a different approach?
Use the TextBox.KeyPress event:
private void txtIn1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsDigit(e.KeyChar) /* || add more conditions*/)
e.Handled = true; // Prevent key to be added to the TextBox' text.
}
Now you don't have to check if there are non-numbers in your string.
Your statement int.Parse(txtIn1.Text); will surely work.
It appears that exceptions that occur in a property's Set method do not bubble up to the Application's ThreadException event.
We use that event along with the AppDomain.CurrentDomain.UnhandledException event to catch any unexpected mishaps that occur in the application. The exception details are written to a log so our support and development team can better evaluate the issue. Sadly it looks like this Catch All falls short in this particular case.
There are several similar questions on StackOverflow, But no answer addresses the issue of the global exception handling not catching the exception. I already know we can fix it so no exception occurs. We could add a TryCatch block to every setter. We could add the BindingComplete event to each databinding and get the exception that way. But all of that defeats the purpose of having global exception handling which works perfectly in any other case.
How do I 'globally' catch exceptions thrown in object instances
Data Binding and throwing exception in setter
Neither Application.ThreadException nor AppDomain.CurrentDomain.UnhandledException are respected
To reproduce the issue, simply create a form with a text box, bind the text box to a property and throw an exception in the property's set method. Add the ThreadException and UnhandledException events to the program.cs. Run the program and type in the text box to trigger the exception. The debugger will break on the exception, press Continue (F5) the let the exception bubble up as it would outside of the debugger. Any normal exception would end up in those events, but this one does not.
Form1.cs
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.DataBindings.Add("Text", this, "TestValue", true, DataSourceUpdateMode.OnPropertyChanged);
}
private string _TestValue = "";
public string TestValue
{
get{return _TestValue;}
set
{
_TestValue = value;
throw new Exception("Something bad happened in here");
}
}
Program.cs
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += ThreadExceptionHandler;
AppDomain.CurrentDomain.UnhandledException += new System.UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
Application.Run(new Form1());
}
private static void ThreadExceptionHandler(object sender, System.Threading.ThreadExceptionEventArgs args)
{
try
{
//RR.Common.ErrorLogRt.WriteError(args.Exception.StackTrace.ToString(), args.Exception.Message.ToString(), true);
MessageBox.Show(args.Exception.Message);
}
catch
{
MessageBox.Show("Error writing to exception log. This program will now terminate abnormally.");
Application.Exit();
}
}
static void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
{
try
{
if (e != null)
{
Exception ex = e.ExceptionObject as Exception;
//RR.Common.ErrorLogRt.WriteError(ex.StackTrace.ToString(), ex.Message.ToString(), true);
MessageBox.Show(ex.Message);
}
else
{
MessageBox.Show("Unhandled Error: " + e.ToString());
}
}
catch
{
MessageBox.Show("Error writing to exception log. This program will now terminate abnormally.");
Application.Exit();
}
}
static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
try
{
if (e != null && e.Exception != null && e.Exception.InnerException != null)
{
//The unobserved exception is always the same, The actual exception that cause it will be the inner exception.
Exception ex = e.Exception.InnerException;
MessageBox.Show(e.Exception.Message);
//RR.Common.ErrorLogRt.WriteError(ex.StackTrace.ToString(), ex.Message.ToString(), true);
}
else
{
MessageBox.Show("Unhandled Error: " + e.ToString());
}
}
catch
{
MessageBox.Show("Error writing to exception log. This program will now terminate abnormally.");
Application.Exit();
}
}
}
Remarks from Binding.FormattingEnabled Property
Setting this property to true also enables error-handling behavior and
causes the BindingComplete event to be raised. The handler of this
event can take the appropriate action, based on the success, error, or
exceptions in the binding process, by examining the
BindingCompleteState property of the BindingCompleteEventArgs
parameter.
The code involved
internal bool PushData(bool force)
{
Exception ex = null;
if (!force && this.ControlUpdateMode == ControlUpdateMode.Never)
{
return false;
}
if (this.inPushOrPull && this.formattingEnabled)
{
return false;
}
this.inPushOrPull = true;
try
{
if (this.IsBinding)
{
object value = this.bindToObject.GetValue();
object propValue = this.FormatObject(value);
this.SetPropValue(propValue);
this.modified = false;
}
else
{
this.SetPropValue(null);
}
}
catch (Exception ex2)
{
ex = ex2;
if (!this.FormattingEnabled)
{
throw;
}
}
finally
{
this.inPushOrPull = false;
}
if (this.FormattingEnabled)
{
BindingCompleteEventArgs bindingCompleteEventArgs = this.CreateBindingCompleteEventArgs(BindingCompleteContext.ControlUpdate, ex);
this.OnBindingComplete(bindingCompleteEventArgs);
return bindingCompleteEventArgs.Cancel;
}
return false;
}
As you can see, passing 4th parameter as true: DataBindings.Add("Text", this, "TestValue", true is responsible for catching the exception inside PushData and passing it to BindingComplete event. There is no other way (except AppDomain.CurrentDomain.FirstChanceException) to find the exception anywhere else than in BindingComplete if formatting is enabled.
I know a solution exists for WPF, but I could not make it work for winforms.
It seems like the exception is somehow trapped by the framework and I cant find the right trace to listen to.
What you could do though is handle first-chance exceptions (beware that this will probably make you catch way more than what you want).
This will show a message box with "Something bad happened in here" in your example:
AppDomain.CurrentDomain.FirstChanceException += OnFirstChanceException;
//...
private static void OnFirstChanceException(object sender, FirstChanceExceptionEventArgs firstChanceExceptionEventArgs)
{
if(firstChanceExceptionEventArgs.Exception is TargetInvocationException)
{
if(firstChanceExceptionEventArgs.Exception.InnerException != null)
MessageBox.Show(firstChanceExceptionEventArgs.Exception.InnerException.Message);
else
MessageBox.Show(firstChanceExceptionEventArgs.Exception.Message);
}
}
If you are curious, this is the WPF solution I was talking about:
https://web.archive.org/web/20140809204919/https://www.tech.pro/tutorial/940/wpf-snippet-detecting-binding-errors
It looks like it has been reported as a defect to Microsoft, who have closed it as 'Won't Fix':
ReflectPropertyDescriptor.SetValue does not preserve stack trace
in the Microsoft Reference Source, the code for the SetValue method (lines 1085 to 1173) contains a block with a structure like this:
try // <--- This ...
{
try
{
// Code to invoke SetMethod.
}
catch(Exception)
{
// Code to rewind.
// Code to throw inner or rethrow.
}
}
finally // <--- ... and this consume the exception before you can handle it.
{
// Code to raise change notification.
}
The outer try ... finally block is consuming the (second chance) exception that is preventing you from handling it in your code. The dbugger can still catch the (first chance) exception, but it wont get out of the SetValue method.
This question already has answers here:
The difference between try/catch/throw and try/catch(e)/throw e
(4 answers)
Closed 8 years ago.
I got here that the next code is anti-pattern. Is it right?
try
{
//something
}
catch(Exception e)
{
//something
}
And why better to use
try
{
//something
}
catch(Exception e)
{
//something
throw;
}
?
I got that second variant is using for re-throwing exception (logging for example), but if I need re-throw the same exception why not use the next code?
try
{
//something
}
catch(Exception e)
{
//something
throw e;
}
This will re-throw the same exception and keep the stack trace. This will make debugging easier.
catch(Exception e)
{
//something
throw;
}
This will rethrow the exception, but you'll lose the stack trace.
catch(Exception e)
{
//something
throw e;
}
This will silently swallow the exception. You only want to do this when you're catching a specific exception rather than Exception. You should generally have a good reason for doing so.
try
{
//something
}
catch(Exception e)
{
//something
}
Here's the code for the event handler involved:
private void textBox1_TextChanged(object sender, EventArgs e)
{
try
{
seed = Convert.ToInt32(this.Text);
}
catch (FormatException)
{
MessageBox.Show("Input string is not a sequence of digits.");
}
catch (OverflowException)
{
MessageBox.Show("The number cannot fit in an Int32.");
}
}
It's supposed to ensure a user doesn't type anything but a number allowable by Int32 into the text box, but the first catch statement executes EVERY time you try to type ANYTHING into the box. I've looked around but I can't seem to figure out why...
Probably because this.Text doesn't read from the input box, but rather the class the handler is defined in.
I believe what you want is:
try
{
seed = Convert.ToInt32(((TextBox)caller).Text);
}
It might be helpful to see the error message, using the following (temporarily of course):
catch (FormatException exception)
{
MessageBox.Show("Input string is not a sequence of digits."
+ "Exception message was: " + exception.getMessage());
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
try
{
seed = Convert.ToInt32(textBox1.text);
}
catch (FormatException)
{
MessageBox.Show("Input string is not a sequence of digits.");
}
catch (OverflowException)
{
MessageBox.Show("The number cannot fit in an Int32.");
}
}
Please use the above statement and it should work correctly. If you type in a number the first exception will not execute.
I have an application where I load an image dynamically. Let's say, that image doesn't exists and we want to notify the user and then exit. In my main loop, I have exception handling which works just fine when I'm reading files with StreamReader. However, if I am throwing exception from another function, the app just crashes and in the error report I see thrown exception (IOException). To get an idea of the app:
public MainWindow()
{
try {
InitializeComponent();
Load(myFile);
} catch (IOException e) {
MessageBox.Show("Opening failure.");
Application.Current.Shutdown();
}
}
public void Load(string imgPath)
{
string tmpStr;
string[] tmp;
using (StreamReader sr = new StreamReader("myFile.txt", System.Text.Encoding.Default)) {
while ((tmpStr = sr.ReadLine()) != null) {
tmp = tmpStr.Split(' ');
...
}
}
}
private void Grid_Click(object sender, RoutedEventArgs e)
{
...
if (!File.Exists(myFile)) {
throw new IOException("File doesnt exist");
}
...
}
BUT, if I put try-catch block inside Grid_Click, it catches that exception.
The exception that is thrown in Grid-Click would not be caught by the catch statement in the MainWindow() method by design, since the method call to Grid_Click is not inside that try block.
The Grid_Click method is called when the click event is fired, which is at an asynchronous time. Only IOExceptions thrown inside the try block in MainWindow will be caught by that catch statement you have listed above.
What you call 'main loop' is just a constructor. The code does not execute under it's control.