How to debug a finally block in Visual Studio? - c#

How do I debug the finally block in a try {...} finally{...} in the event of an uncaught exception? It seems that no matter what I do with the exception settings or debugger, Visual Studio will not let me proceed past the point of the thrown exception in the try block in order to debug the finally code.
Here's a representative, short example:
public static void Main()
{
var instrument = new Instrument();
try
{
instrument.TurnOnInstrument();
instrument.DoSomethingThatMightThrowAnException();
throw new Exception(); // Visual Studio won't let me get past here. Only option is to hit "Stop Debugging", which does not proceed through the finally block
}
finally
{
if(instrument != null)
instrument.TurnOffInstrument();
}
}
Context: I have a program that controls some hardware instruments used for taking electronic measurements in a lab, e.g. programmable PSUs. In the event that something goes wrong, I want it to fail fast: first shut down the instruments to prevent possible physical damage and then exit. The code to shut them down is in the finally block, but I have no way to debug that this code works in the error case. I don't want to try to handle any possible errors, just turn the instruments and then shut the program down. Maybe I'm going about this the wrong way?

A finally block is never executed if the exception results in a crash of the application, that is the case in your code.
To debug the finally block in your exemple, you have to put the whole code of your main function in an other try statement, and catch the exception to prevent the application to crash, like this:
public static void Main()
{
try
{
var instrument = new Instrument();
try
{
instrument.TurnOnInstrument();
instrument.DoSomethingThatMightThrowAnException();
throw new Exception();
}
finally
{
if (instrument != null)
instrument.TurnOffInstrument();
}
}
catch (Exception)
{
Console.Writeline("An exception occured");
}
}

You can set breakpoint ( F9 key ) and Alt + Ctrl + B Keys to see the list of breakpoints.
You can break in between using IntelliTrace, As :

You need to put a breakpoint on the first line inside the finally block, then click "Run" again after the exception.

Related

Certain part of my code is never executed

Problem
Why my line of the code never execute: Console.WriteLine("THIS NOT EXECUTE");
I am not sure, is that about Try-Catch, delegate, or RabbitMQ.
Anyone had something similar?
Progress
There is an exception(that is the reason why a certain part of my code never execute, but why that exception happened is not known):
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
Solution
On my colleague's computer, this works fine, and that part of the code executes... Because of that, I did the following:
deleted project locally
clone repository again
run project
And now everything works fine, but I would like to know what is an initial problem and why that exception happened on my computer?
Code
private EventingBasicConsumer DecodeMessage()
{
SmellDetectionReport reportMessage = new SmellDetectionReport();
var consumer = new EventingBasicConsumer(Channel);
consumer.Received += (model, deliveryArguments) =>
{
var body = deliveryArguments.Body.ToArray();
var jsonMessage = Encoding.UTF8.GetString(body);
try
{
Console.WriteLine("THIS EXECUTE");
reportMessage = JsonConvert.DeserializeObject<SmellDetectionReport>(jsonMessage);
Console.WriteLine("THIS NOT EXECUTE");
}
catch (Exception e)
{
//TODO: write exc
Console.WriteLine("exc");
Console.WriteLine("exc");
}
finally
{
Console.WriteLine("finally");
Console.WriteLine("finally");
}
};
Console.WriteLine("end");
return consumer;
}
Base info
Language: C#
Technology: RabbitMQ
The best thing to do is set a breakpoint by clicking to the left of the line of code at the start of code.received and then pressing f11 to step through the code statement by statement. This will allow you to see the path the code is taking and why it doesn't reach that statement. My initial guess is that the JSON deserialization is failing and so execution moves to the catch block.
catch (Exception e)
{
//TODO: write exc
Console.WriteLine($"exc {e.Message}");
}
Write a catch statement like that to get better idea of exception. Also try to debug the code.

(AccessViolationException was unhandled) How do i implement HandleProcessCorruptedStateExceptions in C#?

I came across a problem that is the AccessViolationException was unhandled after i run my program for about a day long.
(More information: I am using Visual Studio 2010)
However, it does not state where this exception occurs, there were two options given to me which is "ok" and "continue". When i pressed ok, nothing happened so i pressed continue and the program stops debugging.
When i tried to find a solution, i understand that i can implement HandleProcessCorruptedStateExceptions to fix this problem. However, i have no clue where to start.
Do i simply include the codes below only? And where do i include these code?
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
public static int Main()
{
try
{
// Catch any exceptions leaking out of the program CallMainProgramLoop();
}
catch (Exception e)
// We could be catching anything here
{
// The exception we caught could have been a program error
// or something much more serious. Regardless, we know that
// something is not right. We'll just output the exception
// and exit with an error. We won't try to do any work when
// the program or process is in an unknown state!
System.Console.WriteLine(e.Message);
return 1;
}
return 0;
}
Alternatively, i can also do this legacyCorruptedStateExceptionsPolicy but it says that i should input the required statement in the config file. Where can i find the config file?
Appreciate all the replies!
The actual answer for you question is here and I really shouldn't answer it again, but I want to show you some code sample and I don't want to write it in comment :)
In one of my projects from time to time there was an unpredictable exception. To catch it I write this code in Program.cs:
[STAThread]
static void Main()
{
// add UnhandledException handler
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
{
// prepare message for user
var message = "There was an unknown exception while running <app_name>!";
var exception = e.ExceptionObject as Exception;
if (exception != null)
{
// change message if there was actual exception
message = $"There was an {exception.GetType().Name} exception while running <app_name>! {exception.Message}";
// adding inner exceptions messages
var innerException = exception.InnerException;
while (innerException != null)
{
message += $"\r\n-> {innerException.GetType().Name}: {innerException.Message}";
innerException = innerException.InnerException;
}
#if DEBUG
// add tracing info
message += $"\r\n\r\n{GetStackTrace(exception)}";
#endif
}
if (e.IsTerminating) message += "\r\n\r\n<app_name> will be closed.";
// showing message to the user
MessageBox.Show(message, "Unhandled Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
#if DEBUG
private static string GetStackTrace(Exception exception)
{
var trace = new System.Diagnostics.StackTrace(exception, fNeedFileInfo: true);
var frames = trace.GetFrames()
.Select((f, i) => {
var filename = f.GetFileName();
var methodInfo = f.GetMethod();
var frame = $"#{i} in the method {methodInfo.DeclaringType.FullName}.{methodInfo.Name}()";
if (filename != null) frame += $" (source file: {System.IO.Path.GetFileName(filename)}#{f.GetFileLineNumber()}:{f.GetFileColumnNumber()})";
return frame;
});
return $"Full stack trace ({trace.FrameCount} frames total):\r\n{string.Join("\r\n", frames)}";
}
#endif
Now, when unhandled exception occurring - there will be a message box, that shows full exception message (and inner exceptions messages). There was also a full stack trace for Debug build with method name, line number and source filename where exception occure.
About HandleProcessCorruptedStateExceptions
You mention a HandleProcessCorruptedStateExceptions attribute in your comment. The docs clearly says that you shouldn't use it unless you absolutely sure that you need it.
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.
By default, the common language runtime (CLR) does not deliver these
exceptions to managed code, and the try/catch blocks (and other
exception-handling clauses) are not invoked for them. If you are
absolutely sure that you want to maintain your handling of these
exceptions, you must apply the
HandleProcessCorruptedStateExceptionsAttribute attribute to the method
whose exception-handling clauses you want to execute. The CLR delivers
the corrupted process state exception to applicable exception clauses
only in methods that have both the
HandleProcessCorruptedStateExceptionsAttribute and
SecurityCriticalAttribute attributes.
Corrupted process state means that some really catastrophic things happens and it safer for your app to die right now. If you are still not scared enough, here is the Main() method from the example above with the HandleProcessCorruptedStateExceptions attribute set:
[STAThread]
[HandleProcessCorruptedStateExceptions, SecurityCritical]
static void Main()
{
try
{
// add UnhandledException handler
// AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
// * in this particular case is not quite useful to handle this exceptions,
// because you already wrap your entire application in a try/catch block
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
catch (Exception ex)
{
// handle it somehow
}
}

Azure Functions 2.x keep throwing catched exceptions

In my Azure Functions 2.x Project, i have a part of an Function, a try-catch block without finally, that more or less look like this.
Dictionary<string, int> varDict = null;
Tuple<string, DateTime> varTupl = null;
try
{
varDict = await Core.GetDict(lcLat.Value, lcLong.Value);
varTupl = await Core.GetTupl(lcLat.Value, lcLong.Value);
}
catch (AggregateException ae)
{
ae.Flatten().Handle(ex =>
{
// `log` is an ILogger, the standard Azure Functions passed param
log.LogError(ex, ""); // Writes the ex's error
Debug.WriteLine(""); // Writes the ex's error
// the written content is ommited for readability sake
// But will be shown below
return true;
});
}
catch (Exception ex)
{
// Does exactly like Handle() Does
}
if(varDict != null && varTupl != null)
{
// The Code won't go here, and always return HTTP 500 Instead
}
else
{
// Here neither
}
The Run method itself is an async Task<IActionResult>, with Core as a static public class containing GetDict() and GetTupl() methods, each of them are also an static async Task<T> with their respective T return type and both doesn't have any try-catch block, only using (which are not supposed to throw any exceptions, right ?)
The problem is, even though (i assume) the exceptions raised then bubbled up into my try-catch block, even with my catch block running printing the exception with my formatting from catch block, as shown in the screenshot ,my Azure Functions keep returning HTTP Error 500, skipping the rest of the code after the try-catch block
What i have tried
Disable 'Just My Code' debugging options in my Visual Stuido 2017
Adding AggregateExceptions, before this it's only catching for Exception
Flatten the AggregateException before Handle() it
Is this common on local development environment, or it's just me handling everything incorectly ?
Also, the output window keep printing out something like this
and this
even in idle state (while the HTTP endpoint isn't being invoked, just run in debug mode, idly waiting for invocation)
are these something that i have to concerned about ? are those even related with my problem

Why is this finally not executing?

.net 4 console app sample
When I run this in the vs 2010 it seems to keep throwing (from the catch) and never gets to the finally. It breaks on the throw and shows the exception, I hit f5 and it rethrows almost like its looping on the throw. Using similiar code in another exe I was able to throw the exception to the console and execute the finally to clean up. That is not the case not and I'm wondering why.
static void Main(string[] args)
{
try
{
throw new Exception("Exception");
}
catch(Exception)
{
Console.WriteLine("Catch");
throw;
}
finally
{
Console.WriteLine("Finally");
}
}
On the contrary, it does execute the finally block. This is the output:
Catch
Unhandled Exception: System.Exception: Exception at ConsoleApplication1.Program.Main(String[] args) in C:\Desktop\ConsoleApplication1\Program.cs:line 24
Finally
I would bet the finally actually is executed, but being in the Main method of the console application, in the finally the console object is not available anymore.
If I start the program with debugging, the code stops with the message "unhandled exception", which is before finally would be executed. Running without debugging will work as intended (CTRL-F5).
Using the debugger you can verify the finally being executed by moving your testcode inside another try-catch block, e.g.:
static void Main(string[] args)
{
try
{
Method();
}
catch (Exception)
{
Console.WriteLine("caught in main");
}
Console.ReadKey();
}
public static void Method()
{
try
{
throw new Exception("Exception");
}
catch (Exception)
{
Console.WriteLine("Catch");
throw;
}
finally
{
Console.WriteLine("Finally");
}
}
You can guarantee that it is indeed executing, as #David Heffernan demonstrated with his output; however, you might consider what is said in the C# specification (8.10) in order be confident that is should be:
The statements of a finally block are always executed when control
leaves a try statement. This is true whether the control transfer
occurs as a result of normal execution, as a result of executing a
break, continue, goto, or return statement, or as a result of
propagating an exception out of the try statement.

Ignoring try block in C# command line program

I have a command line program in C# that I've wrapped with a try-catch block to keep it from crashing the console. However, while I am debugging it, if an exception is thrown somewhere in the DoStuff() method, Visual Studio will break on the "catch" statement. I want Visual Studio to break where the exception occurred. What's the best way to do this?
Comment out the try?
A setting in Visual Sudio?
An #if DEBUG statement?
static void Main(string[] args)
{
try
{
DoStuff();
}
catch (Exception e)
{ //right now I have a breakpoint here
Console.WriteLine(e.Message);
}
}
private void DoStuff()
{
//I'd like VS to break here if an exception is thrown here.
}
You can turn on First chance exceptions in VS. This will allow you to be notified as soon as an exception is raised.
I think setting VS to break on uncaught exceptions and wrapping the try/catch in ifdefs is how I would go about doing it.
There is an option to "Break on all exceptions". I'm not sure what version of VS you are using but in VS 2008 you can press Ctrl + D, E. You can then click the checkbox the Thrown checkbox for the types of exceptions you want to break on
I believe in previous versions of VS there was a Debug menu item to the effect of "Break on all exceptions". Unfortunately I don't have a previous version handy.
Here's how I do it for console tools running at continuous integration server:
private static void Main(string[] args)
{
var parameters = CommandLineUtil.ParseCommandString(args);
#if DEBUG
RunInDebugMode(parameters);
#else
RunInReleaseMode(parameters);
#endif
}
static void RunInDebugMode(IDictionary<string,string> args)
{
var counter = new ExceptionCounters();
SetupDebugParameters(args);
RunContainer(args, counter, ConsoleLog.Instance);
}
static void RunInReleaseMode(IDictionary<string,string> args)
{
var counter = new ExceptionCounters();
try
{
RunContainer(args, counter, NullLog.Instance);
}
catch (Exception ex)
{
var exception = new InvalidOperationException("Unhandled exception", ex);
counter.Add(exception);
Environment.ExitCode = 1;
}
finally
{
SaveExceptionLog(parameters, counter);
}
}
Basically, in release mode we trap all unhandled exceptions, add them to the global exception counter, save to some file and then exit with error code.
In debug more exception goes right to the throwing spot, plus we use console logger by default to see what's happening.
PS: ExceptionCounters, ConsoleLog etc come from the Lokad Shared Libraries

Categories

Resources