How to suppress exceptions coming from assemblies [duplicate] - c#

I am using a COM object (MODI) from within my .net application. The method I am calling throws a System.AccessViolationException, which is intercepted by Visual Studio. The odd thing is that I have wrapped my call in a try catch, which has handlers for AccessViolationException, COMException and everything else, but when Visual Studio (2010) intercepts the AccessViolationException, the debugger breaks on the method call (doc.OCR), and if I step through, it continues to the next line instead of entering the catch block. Additionally, if I run this outside of the visual studio my application crashes. How can I handle this exception that is thrown within the COM object?
MODI.Document doc = new MODI.Document();
try
{
doc.Create(sFileName);
try
{
doc.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, false, false);
sText = doc.Images[0].Layout.Text;
}
catch (System.AccessViolationException ex)
{
//MODI seems to get access violations for some reason, but is still able to return the OCR text.
sText = doc.Images[0].Layout.Text;
}
catch (System.Runtime.InteropServices.COMException ex)
{
//if no text exists, the engine throws an exception.
sText = "";
}
catch
{
sText = "";
}
if (sText != null)
{
sText = sText.Trim();
}
}
finally
{
doc.Close(false);
//Cleanup routine, this is how we are able to delete files used by MODI.
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(doc);
doc = null;
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}

EDIT (3/17/2021)
Disclaimer: This answer was written in 2011 and references the original .NET Framework 4.0 implementation, NOT the open-source implementation of .NET.
In .NET 4.0, the runtime handles certain exceptions raised as Windows Structured Error Handling (SEH) errors as indicators of Corrupted State. These Corrupted State Exceptions (CSE) are not allowed to be caught by your standard managed code. I won't get into the why's or how's here. Read this article about CSE's in the .NET 4.0 Framework:
http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035
But there is hope. There are a few ways to get around this:
Recompile as a .NET 3.5 assembly and run it in .NET 4.0.
Add a line to your application's config file under the configuration/runtime element:
<legacyCorruptedStateExceptionsPolicy enabled="true|false"/>
Decorate the methods you want to catch these exceptions in with the HandleProcessCorruptedStateExceptions attribute. See http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035 for details.
EDIT
Previously, I referenced a forum post for additional details. But since Microsoft Connect has been retired, here are the additional details in case you're interested:
From Gaurav Khanna, a developer from the Microsoft CLR Team
This behaviour is by design due to a feature of CLR 4.0 called Corrupted State Exceptions. Simply put, managed code shouldnt make an attempt to catch exceptions that indicate corrupted process state and AV is one of them.
He then goes on to reference the documentation on the HandleProcessCorruptedStateExceptionsAttribute and the above article. Suffice to say, it's definitely worth a read if you're considering catching these types of exceptions.

Add the following in the config file, and it will be caught in try catch block.
Word of caution... try to avoid this situation, as this means some kind of violation is happening.
<configuration>
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true" />
</runtime>
</configuration>

Compiled from above answers, worked for me, did following steps to catch it.
Step #1 - Add following snippet to config file
<configuration>
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true" />
</runtime>
</configuration>
Step #2
Add -
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
on the top of function you are tying catch the exception
source: http://www.gisremotesensing.com/2017/03/catch-exception-attempted-to-read-or.html

Microsoft: "Corrupted process state exceptions are exceptions that indicate that the state of a process has been corrupted. We do not recommend executing your application in this state.....If you are absolutely sure that you want to maintain your handling of these exceptions, you must apply the HandleProcessCorruptedStateExceptionsAttribute attribute"
Microsoft: "Use application domains to isolate tasks that might bring down a process."
The program below will protect your main application/thread from unrecoverable failures without risks associated with use of HandleProcessCorruptedStateExceptions and <legacyCorruptedStateExceptionsPolicy>
public class BoundaryLessExecHelper : MarshalByRefObject
{
public void DoSomething(MethodParams parms, Action action)
{
if (action != null)
action();
parms.BeenThere = true; // example of return value
}
}
public struct MethodParams
{
public bool BeenThere { get; set; }
}
class Program
{
static void InvokeCse()
{
IntPtr ptr = new IntPtr(123);
System.Runtime.InteropServices.Marshal.StructureToPtr(123, ptr, true);
}
private static void ExecInThisDomain()
{
try
{
var o = new BoundaryLessExecHelper();
var p = new MethodParams() { BeenThere = false };
Console.WriteLine("Before call");
o.DoSomething(p, CausesAccessViolation);
Console.WriteLine("After call. param been there? : " + p.BeenThere.ToString()); //never stops here
}
catch (Exception exc)
{
Console.WriteLine($"CSE: {exc.ToString()}");
}
Console.ReadLine();
}
private static void ExecInAnotherDomain()
{
AppDomain dom = null;
try
{
dom = AppDomain.CreateDomain("newDomain");
var p = new MethodParams() { BeenThere = false };
var o = (BoundaryLessExecHelper)dom.CreateInstanceAndUnwrap(typeof(BoundaryLessExecHelper).Assembly.FullName, typeof(BoundaryLessExecHelper).FullName);
Console.WriteLine("Before call");
o.DoSomething(p, CausesAccessViolation);
Console.WriteLine("After call. param been there? : " + p.BeenThere.ToString()); // never gets to here
}
catch (Exception exc)
{
Console.WriteLine($"CSE: {exc.ToString()}");
}
finally
{
AppDomain.Unload(dom);
}
Console.ReadLine();
}
static void Main(string[] args)
{
ExecInAnotherDomain(); // this will not break app
ExecInThisDomain(); // this will
}
}

You can try using AppDomain.UnhandledException and see if that lets you catch it.
**EDIT*
Here is some more information that might be useful (it's a long read).

Related

How can I have an exception show in debugging output that doesn't cause a "catch"

This may be a basic question but I have not been able to find an answer from searching. I have code that is causing an exception to be written to the Output -> Debug window in Visual Studio. My try...catch is proceeding to the next line of code anyway. The exception is with a NuGet package.
Does this mean an exception is happening in the NuGet package and is handled by the Nuget package? How can I troubleshoot this further?
private void HandleStorageWriteAvailable(IXDocument doc)
{
using IStorage storage = doc.OpenStorage(StorageName, AccessType_e.Write);
{
Debug.WriteLine("Attempting to write to storage.");
try
{
using (Stream str = storage.TryOpenStream(EntityStreamName, true))
{
if (str is not null)
{
try
{
string test = string.Concat(Enumerable.Repeat("*", 100000));
var xmlSer = new XmlSerializer(typeof(string));
xmlSer.Serialize(str, test);
}
catch (Exception ex)
{
Debug.WriteLine("Something bad happened when trying to write to the SW file.");
Debug.WriteLine(ex);
}
}
else
{
Debug.WriteLine($"Failed to open stream {EntityStreamName} to write to.");
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
}
The exception happens on the line using (Stream str = storage.TryOpenStream(EntityStreamName, true)) when the exception happens the code proceeds to the next line not the catch.
Is this normal behaviour if that exception is being handled by something else? I've never seen this before.
In general, a method called TrySomething will be designed so that it won't throw an exception, but return some sort of error code instead.
Check for example the Dictionary class : it has an Add method which can throw an ArgumentException if the key already exists, and a TryAdd method which instead just returns false.
Chances are, your IStorage implementation of TryOpenStream also has an OpenStream method, and the Try version is just a try/catch wrapper which outputs the error to the Console in case of error.
How do you know it happens on that line?
However there is a setting that enables breaking handled exception in "Exception Settings" dialog (Ctrl+Alt+E). For each type of exception you can control. Here is a link that explain how it works : https://learn.microsoft.com/en-us/visualstudio/debugger/managing-exceptions-with-the-debugger?view=vs-2022

C# Cannot catch exceptions from another project within same solution

Got a strange problem: in a complex camera control program I'm working on, I use an SDK with a C# wrapper that was programmed by someone else. I include the wrapper as a separate project within the same solution. My own code is a WPF project that uses numerous calls into the SDK.
Everything synchronous works fine. However, depending on camera responses, the SDK occasionally sends asynchronous responses, usually in the form of throwing a custom exception with info about an error the camera reports. I implemented this using
try { ... } catch (ThisExceptionType) { ... }
However, NO exception ever gets caught. When an exception situation occurs, VisualStudio breaks, shows me the code where the SDK throws it and reports "ThisExceptionType was unhandled by user code", also showing the details of the exception condition (meaning it was apparently thrown properly). I verified that the exception corresponds with the error condition I created, so I'm sure I'm not looking at the wrong part of my code.
For testing purposes, I also replaced the line in the SDK where it throws ThisExceptionType with a standard exception, such as throw new ArgumentException("Test"); Same result: when changing my catch to catch (ArgumentException), I still cannot catch the condition and get a similar unhandled-by-user-code error.
Here's how the SDK throws the exception:
void CallEntryPoint( ...)
{
eNkMAIDResult result = _md3.EntryPoint(...);
switch (result)
{
// Note: Ignore these return values
case eNkMAIDResult.kNkMAIDResult_NoError:
case eNkMAIDResult.kNkMAIDResult_Pending:
break;
default:
throw new NikonException(...);
}
}
What am I missing here? Sorry if this is a simple issue - I'm pretty experienced in general programming but have not worked much with VisualStudio, and not a whole lot in C#, either.
UPDATE: According to the wrapper's author (this is actually Thomas Dideriksen's Nikon SDK wrapper), "when you're writing WPF or WinForms application, the C# wrapper relies on the inherent windows message queue to fire events on the UI thread."
He also states that the wrapper processes all camera tasks sequentially, so I guess my statement was incorrect about the wrapper throwing asynchronous exceptions - all code examples for the wrapper use the same try { ... } catch (ThisExceptionType) { ... } approach. For good measure, I tried some of your suggestions, for instance by hooking a handler to AppDomain.CurrentDomain.UnhandledException, but that approach failed to catch the exception, as well.
Any other ideas why this may be happening?
This article on MSDN may help. https://msdn.microsoft.com/en-us/library/dd997415(v=vs.110).aspx
There are differences in handling exceptions using Tasks in C#. Hopefully that will give a run down on different techniques you can use to handle the exceptions appropriately.
From the MSDN article:
Unhandled exceptions that are thrown by user code that is running
inside a task are propagated back to the calling thread, except in
certain scenarios that are described later in this topic. Exceptions
are propagated when you use one of the static or instance Task.Wait or
Task.Wait methods, and you handle them by enclosing the call
in a try/catch statement. If a task is the parent of attached child
tasks, or if you are waiting on multiple tasks, multiple exceptions
could be thrown.
And there are a couple solutions provided:
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );
try
{
task1.Wait();
}
catch (AggregateException ae)
{
foreach (var e in ae.InnerExceptions) {
// Handle the custom exception.
if (e is CustomException) {
Console.WriteLine(e.Message);
}
// Rethrow any other exception.
else {
throw;
}
}
}
}
}
public class CustomException : Exception
{
public CustomException(String message) : base(message)
{}
}
// The example displays the following output:
// This exception is expected!
Or you can do this:
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );
while(! task1.IsCompleted) {}
if (task1.Status == TaskStatus.Faulted) {
foreach (var e in task1.Exception.InnerExceptions) {
// Handle the custom exception.
if (e is CustomException) {
Console.WriteLine(e.Message);
}
// Rethrow any other exception.
else {
throw e;
}
}
}
}
}
public class CustomException : Exception
{
public CustomException(String message) : base(message)
{}
}
// The example displays the following output:
// This exception is expected!
I hope that helps!

Why does this terminate my app without throwing an exception?

I am using the YAX Serializer (current NuGet version). When I run this code:
void Main()
{
try
{
int zero = 0;
int result = 100 / zero;
}
catch (DivideByZeroException ex)
{
LogSaveException(ex);
}
}
public void LogSaveException(object value)
{
try
{
YAXSerializer serializer = new YAXSerializer(value.GetType());
string loggedString = serializer.Serialize(value);
Console.WriteLine(loggedString);
}
catch (StackOverflowException)
{
Console.WriteLine("Log Error", "Could Not Log object of type "
+ value.GetType().ToString() +" due to stack overflow.");
}
catch (Exception)
{
Console.WriteLine("Log Error", "Could Not Log object of type "
+ value.GetType().ToString());
}
}
The app ends on this line: string loggedString = serializer.Serialize(value);
I have tried to catch any exception that I can see would happen. But the app just ends.
I tried running it in LinqPad and it crashed LinqPad. I tried to debug the crash of LinqPad (even though I do not have the source, sometimes you can get some info from it.) When I did that it said that there was a StackOverflowException. But my catch statement did not catch it.
What would cause a total death like that? How how do I guard against it?
Stackoverflow exceptions have limited "catchability" in CLR > 2.0. See the blog post below for more details; the behavior you're experiencing is exactly what's described.
See: http://blogs.msdn.com/b/jaredpar/archive/2008/10/22/when-can-you-catch-a-stackoverflowexception.aspx
While annoying, this does make sense: if you've blown your stack, what would a consistent/safe/sane recovery look like?
Seems like a serious error with the YAXSerializer.
StackOverflowException cannot be caught (see here amongst others for reference) because there's rarely any recovery from such a serious error.
EDIT: or it's an error with the class you're serializing. Do you have a cyclic reference in the object you're passing in?

Using try-catch between multiple routines

This is somewhat of a follow up to a previous question I had asked, although I am now able to provide a lot more code to improve my question and further show my trouble with this area.
I have three routines here. Two of these routines work together - and if successful, will load an assembly into memory using System.Reflection. I would like for these routines to return an error if the file did not load properly into memory, but for some reason these try-catch statements simply will not work the way I would like.
Note: For this routine to work the file must be a .net assembly. If, for example, the file was programmed in VB6 an error will be thrown. This is the error I am trying to have returned to me.
private void ExecuteDataIntoMemory(string filePath)
{
byte[] bytes = File.ReadAllBytes(filePath);
try
{
ExecFile(bytes);
MessageBox.Show("successfully loaded this file into memory");
}
catch
{
MessageBox.Show("Could not load this file into memory");
}
}
private static void ExecFile(byte[] data)
{
try
{
//Work around for "SetCompatibleTextRenderingDefault"
System.Threading.Thread T = new System.Threading.Thread(ExecFile);
//Set STA to support drag/drop and dialogs?
T.SetApartmentState(System.Threading.ApartmentState.STA);
T.Start(data);
}
catch
{
MessageBox.Show("caught some error ...");
}
}
private static void ExecFile(object o)
{
System.Reflection.MethodInfo T = System.Reflection.Assembly.Load((byte[])o).EntryPoint;
if (T.GetParameters().Length == 1)
T.Invoke(null, new object[] { new string[] { } });
else
T.Invoke(null, null);
}
I can clarify more if necessary but I'm not sure what other information to include at this point.
Use the "throw" statement within the catch statement of ExecFile to raise the same "exception" (or error) caught in ExecFile. For example:
catch {
throw;
}
I think I figured out the problem though. ExecFile(byte[]) starts the thread and returns immediately without waiting for the thread to exit. To allow that method to wait for the thread to exit, add:
T.Join();
right after starting the thread. (To avoid possible ambiguity, however, you should rename ExecFile(object). I'm also not sure whether ExecFile(byte[]) will catch the exception from ExecFile(object).)
If I understand you well, You want the ExecuteDataIntoMemory to be evaluated only if the ExecFile succeed.
1- You are running a new thread to execute the ExecFile method which will be executed in a different thread. So first at the try block in ExecFile(byte[] data) run the ExecFile(data) without a new Thread because you want to wait for it any way:
try
{
ExecFile(data);
}
2- Notice that you have two method with the same name 'ExecFile(byte[] data)' and ExecFile(object o) the data you are passing is from type byte[] so it will be infinite recursive or till stack over flow exception is raised. So you should cast data to object and then pass it to the method i.e:
try
{
ExecFile((object)data);
}
3- At the catch block of the ExecFile(byte[] data) method rethrow the exception so it can be handled from the caller method two i.e:
try
{
ExecFile((object)data);
}
catch
{
MessageBox.Show("caught some error ...");
throw;
}
If you catch the Exception in ExecFile(byte[] data) it won't be propagated in your parent method (ExecuteDataIntoMemory(string filePath)), and then won't be catched again
If you really need to catch your exception twice, rewrite your child method this way
private static void ExecFile(byte[] data)
{
try
{
//Work around for "SetCompatibleTextRenderingDefault"
System.Threading.Thread T = new System.Threading.Thread(ExecFile);
//Set STA to support drag/drop and dialogs?
T.SetApartmentState(System.Threading.ApartmentState.STA);
T.Start(data);
}
catch (Exception ex)
{
MessageBox.Show("caught some error ...");
throw ex;
}
}
If not, simply not try..catch errors in this method, and the Exception will be propagated..
Just look in the callstack which method call the ExecuteDataIntoMemory method again?
if you are using Visual studio IDE put a breakpoint at the messagebox:
MessageBox.Show("successfully loaded this file into memory");
then simple go to the view menu, from there find the callstack window to display and look at the callstack (show external code to the callstack)
maybe this could help.
The rough way (I think), but should work in your case, is subscribe to
AppDomain.CurrentDomain.UnhandledException
event riased, which will get the exception raised directly from the function ExecFile(object o);
Or create a state machine which is set to NEGATIVE state in case of any exception in ExecFile(object o); method.
Or just do not do it in multithreading :)

How to handle AccessViolationException

I am using a COM object (MODI) from within my .net application. The method I am calling throws a System.AccessViolationException, which is intercepted by Visual Studio. The odd thing is that I have wrapped my call in a try catch, which has handlers for AccessViolationException, COMException and everything else, but when Visual Studio (2010) intercepts the AccessViolationException, the debugger breaks on the method call (doc.OCR), and if I step through, it continues to the next line instead of entering the catch block. Additionally, if I run this outside of the visual studio my application crashes. How can I handle this exception that is thrown within the COM object?
MODI.Document doc = new MODI.Document();
try
{
doc.Create(sFileName);
try
{
doc.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, false, false);
sText = doc.Images[0].Layout.Text;
}
catch (System.AccessViolationException ex)
{
//MODI seems to get access violations for some reason, but is still able to return the OCR text.
sText = doc.Images[0].Layout.Text;
}
catch (System.Runtime.InteropServices.COMException ex)
{
//if no text exists, the engine throws an exception.
sText = "";
}
catch
{
sText = "";
}
if (sText != null)
{
sText = sText.Trim();
}
}
finally
{
doc.Close(false);
//Cleanup routine, this is how we are able to delete files used by MODI.
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(doc);
doc = null;
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
EDIT (3/17/2021)
Disclaimer: This answer was written in 2011 and references the original .NET Framework 4.0 implementation, NOT the open-source implementation of .NET.
In .NET 4.0, the runtime handles certain exceptions raised as Windows Structured Error Handling (SEH) errors as indicators of Corrupted State. These Corrupted State Exceptions (CSE) are not allowed to be caught by your standard managed code. I won't get into the why's or how's here. Read this article about CSE's in the .NET 4.0 Framework:
http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035
But there is hope. There are a few ways to get around this:
Recompile as a .NET 3.5 assembly and run it in .NET 4.0.
Add a line to your application's config file under the configuration/runtime element:
<legacyCorruptedStateExceptionsPolicy enabled="true|false"/>
Decorate the methods you want to catch these exceptions in with the HandleProcessCorruptedStateExceptions attribute. See http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035 for details.
EDIT
Previously, I referenced a forum post for additional details. But since Microsoft Connect has been retired, here are the additional details in case you're interested:
From Gaurav Khanna, a developer from the Microsoft CLR Team
This behaviour is by design due to a feature of CLR 4.0 called Corrupted State Exceptions. Simply put, managed code shouldnt make an attempt to catch exceptions that indicate corrupted process state and AV is one of them.
He then goes on to reference the documentation on the HandleProcessCorruptedStateExceptionsAttribute and the above article. Suffice to say, it's definitely worth a read if you're considering catching these types of exceptions.
Add the following in the config file, and it will be caught in try catch block.
Word of caution... try to avoid this situation, as this means some kind of violation is happening.
<configuration>
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true" />
</runtime>
</configuration>
Compiled from above answers, worked for me, did following steps to catch it.
Step #1 - Add following snippet to config file
<configuration>
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true" />
</runtime>
</configuration>
Step #2
Add -
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
on the top of function you are tying catch the exception
source: http://www.gisremotesensing.com/2017/03/catch-exception-attempted-to-read-or.html
Microsoft: "Corrupted process state exceptions are exceptions that indicate that the state of a process has been corrupted. We do not recommend executing your application in this state.....If you are absolutely sure that you want to maintain your handling of these exceptions, you must apply the HandleProcessCorruptedStateExceptionsAttribute attribute"
Microsoft: "Use application domains to isolate tasks that might bring down a process."
The program below will protect your main application/thread from unrecoverable failures without risks associated with use of HandleProcessCorruptedStateExceptions and <legacyCorruptedStateExceptionsPolicy>
public class BoundaryLessExecHelper : MarshalByRefObject
{
public void DoSomething(MethodParams parms, Action action)
{
if (action != null)
action();
parms.BeenThere = true; // example of return value
}
}
public struct MethodParams
{
public bool BeenThere { get; set; }
}
class Program
{
static void InvokeCse()
{
IntPtr ptr = new IntPtr(123);
System.Runtime.InteropServices.Marshal.StructureToPtr(123, ptr, true);
}
private static void ExecInThisDomain()
{
try
{
var o = new BoundaryLessExecHelper();
var p = new MethodParams() { BeenThere = false };
Console.WriteLine("Before call");
o.DoSomething(p, CausesAccessViolation);
Console.WriteLine("After call. param been there? : " + p.BeenThere.ToString()); //never stops here
}
catch (Exception exc)
{
Console.WriteLine($"CSE: {exc.ToString()}");
}
Console.ReadLine();
}
private static void ExecInAnotherDomain()
{
AppDomain dom = null;
try
{
dom = AppDomain.CreateDomain("newDomain");
var p = new MethodParams() { BeenThere = false };
var o = (BoundaryLessExecHelper)dom.CreateInstanceAndUnwrap(typeof(BoundaryLessExecHelper).Assembly.FullName, typeof(BoundaryLessExecHelper).FullName);
Console.WriteLine("Before call");
o.DoSomething(p, CausesAccessViolation);
Console.WriteLine("After call. param been there? : " + p.BeenThere.ToString()); // never gets to here
}
catch (Exception exc)
{
Console.WriteLine($"CSE: {exc.ToString()}");
}
finally
{
AppDomain.Unload(dom);
}
Console.ReadLine();
}
static void Main(string[] args)
{
ExecInAnotherDomain(); // this will not break app
ExecInThisDomain(); // this will
}
}
You can try using AppDomain.UnhandledException and see if that lets you catch it.
**EDIT*
Here is some more information that might be useful (it's a long read).

Categories