H
We have log utility function that we call pretty often and I wanted to spice it up by adding a call to Server.GetLastError() and if there is an error to log as well.
The log function is part of separate project so I tried to use HttpContext.Current.Server.GetLastError() (As I do for the Request, ServerVariables and Session properties).
During the testing I created simple exception:
int i=0, j=0;
try
{
int k = i / j;
}
catch (Exception E)
{
Tools.CooLog("in");
}
Tools.CooLog("out");
In order to find out if "HttpContext.Current.Server.GetLastError()" will return the exception when Tools.CooLog("out"); is called.
Instead I had two big surprises
1. In both of the calls HttpContext.Current.Server.GetLastError() returned null.
2. And maybe the weirdest is that during the first call of CooLog in the locals section I saw a bit of my young, handsome and PHP version - I saw that there is value called $exception and surprisingly it ha the exception that HttpContext.Current.Server.GetLastError() failed to retrieve!
So my questions are
1. Why the HttpContext.Current.Server.GetLastError() returns null ? (HttpContext.Current.Request.ServerVariables works fine)
2. Where that $exception comes from? is there a way to use it? (in the second call to CooLog the variable is undefined)
That is a special debugger variable. You cannot access it via code.
The reason you don't see it in the Watch window, is that the exception has either been:
Handled
or
The Application.Error event has not been fired yet.
$exception is just the exception that was the reason the debugger paused execution of your program. This is the same as the exception you can access in your catch block, in your case E.
Related
Here is the brief explanation for my script task in SSIS.
Read/Write variable LOGERROR, and it does exist in the Variables panel with string type.
Inside the script, C# code:
try
{
... //what here does is to iterate a folder and move all of them to another folder, codes here are working correctly
Dts.TaskResult = (int)ScriptResults.Success;
}
catch(Exception e)
{
Variables lockedVariables = null;
Dts.VariableDispenser.LockOneForWrite("User::LOGERROR", ref lockedVariables);
lockedVariables["User::LOGERROR"].Value = e.ToString();
lockedVariables.Unlock();
Dts.TaskResult = (int)ScriptResults.Failure;
}
The reason that I manually control the writes of the variable is that the same variable LOGERROR was added to the Event Handler for the same purpose of Point 4.
I direct the Failure to another Execute SQL task, which is trying to insert LOGERROR (Should contain the exception details) into an underlying table.
My questions:
Sometimes the SSISPackage failed at above task (not always, but at almost the same time every day, may have conflicts with the other jobs?) for not any apparent reasons (at least for now). That's why I would like to track what exactly the issue is, but if I query the target logging table. The details does not show anything, just empty.
And, I have a general logging task in Event Handler that logged all the message when task ran with errors. And that message shows nothing but Exception has been thrown by the target of an invocation.
Did I miss something when trying to log LOGERROR? Because it seems for me that the script did not go into the Try & Catch, just failed directly, otherwise it should store the Exception details. (Please correct me if I am wrong). Or, how could I track the error details?
After some investigations, I think the issue was caused by SQL Server Agent failed to access the shared folder during certain time frame.
Possible solution to my questions:
https://social.technet.microsoft.com/Forums/azure/en-US/988207fe-5a25-4da7-a8df-a38fada703da/ssis-script-task-exception-has-been-thrown-by-target-of-invocation?forum=sqlintegrationservices
I am quite new to WPF but find AMAZING to be able to trap any unhandled exception. I have put
this.Dispatcher.UnhandledException += Dispatcher_UnhandledException;
in the constructor of my class. This leads me to trap it with
private void Dispatcher_UnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
...
}
At first it didn't work but then I've seen that to make it work I have to run it in release and outside VS IDE. So that works.
What I'd like is to get as much as info as possible about what caused the exception. Possibly the exception type, the s/r, the line and whatever else is provided.
At the moment by doing
int a = 0;
int b = 3 / a;
and by putting
MessageBox.Show(e.ToString() + " " + sender.ToString());
I get:
so that's not the right way.
I know that I am not putting the necessary information in the question but I have searched through various answer but none reported what I need. If so it can be useful to save any data prior closing but not about closing but not to detected what caused the exception
What's more when I exit with
Environment.Exit(-1)
I find the process still running and that's a problem.
Here Terminate application after unhandled exception it says that I have to kill my process is it really the right way to close my application after an unhandled exception?
Thanks for any help
The actual exception that caused the application to crash is wrapped inside the DispatcherUnhandledExceptionEventArgs parameter.
Simply use e.Exception to get hold of it.
MessageBox.Show(e.Exception.ToString());
After displaying the exception, I would suggest allowing the application to continue by calling the base method:
base.OnUnhandledException(sender, e);
You may choose to mark the exception as handled of course, however in the case of when you are simply overriding this method to display the error, I would not count that as handled.
In .NET, the default exception handler will let the user continue running the program. However, I'd like to have a global exception handler that saves the stack trace to an "errorlog.txt" file so the user can send it to me and doesn't have to remember to click "Details" and copy it out of the dialog (and remove all the useless crap about loaded assemblies and such). But when I do this, the code doesn't know how to continue, so all I can do is exit the app. Is there any way to have the best of both worlds? (Yes, I know what I'm asking for is essentially "On Error Resume Next" with logging, but I really think it would be useful!)
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
If you bind yourself to this event when the application starts, you should be able to catch any Unhandled Exception your application throws, and save it to a file. (Use the Exception object part of the UnhandledExceptionEventArgs. I do not believe it is possible to resume from where the error Occurred.
You can write a global exception handler method that you call in every catch block, which writes the stack trace where ever you want to save it. But you'd need to write try . . . catch blocks for every operation that needs them and call the exception handler in each.
You can also call that global exception handler method in the MyApplication.UnhandledException handler for all unhandled events. But when control gets to that method in that case, the program is not going to continue running.
In a Winform app you can attach an handler to the Application.ThreadException event (make sure you do before calling Application.Run()). This will get rid of the standard exception dialog (the one with the "details" button) and give you the power to display / log anything you want.
However, remember that this will work ONLY for exceptions thrown within the UI thread. Exceptions raised from a background thread won't be reachable from your handler. These can still be caught by AppDomain.UnhandledException handler, though.
in main constructor, put this and will do it globally:
AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
{
MessageBox.Show(eventArgs.Exception.ToString());
};
(Note: as said in comments, this might not be thread-safe).
No that does not exist, exceptions are a flow control construct, so On Error Resume Next is not possible.
You could do your operation in a loop and on an exception, retry your logic.
KandallFrey is right however, you shouldn't use exceptions as flow control, use them only in exceptional cases.
I use My.Application.UnhandledException to open a dialog form where the user can save every information about the exception.
When the form is closed I call e.ExitApplication = False.
At my firm, I've built an exception handling framework which has served me well for 7 years now. Every assembly references the DLL, and every method in each assembly has a try-catch block. In the catch, I basically have to make one decision based on the question "where do I want my exception handling framework to intervene, i.e. to log the exception data externally and inform the user of the problem?". In most cases, the answer to this question is that I want it to intervene in cases where the method is called externally, e.g. if it's inside an event handler or other delegate. So here is some example code:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Try
Method1()
Catch ex As Exception
BSExceptionHandler.ProcessException(BSExceptionHandler.GetBSException(ex, BSExceptionHandler.GetThisMethodName))
End Try
End Sub
Private Sub Method1()
Try
method2()
Catch ex As Exception
Throw BSExceptionHandler.GetBSException(ex, BSExceptionHandler.GetThisMethodName)
End Try
End Sub
Private Sub method2()
Try
Dim x As Integer = CInt("x") 'exception thrown here.
Catch ex As Exception
Throw BSExceptionHandler.GetBSException(ex, BSExceptionHandler.GetThisMethodName)
End Try
End Sub
When Throw BSExceptionHandler.GetBSException(ex, BSExceptionHandler.GetThisMethodName) is called for the first time in Method2(), the original exception is wrapped inside a BSException, and the original method name is stored as well (more on that later). Any subsequent calls to BSExceptionHandler.GetBSException(ex, BSExceptionHandler.GetThisMethodName), e.g. in Method1(), will recognize that the exception is already of type BSException and just throw that instead of re-wrapping it. Ultimately, it reaches the "top" of the call stack (not really the top, just the point at which I've decided I want to process the exception through my framework -- i.e. log it, inform the user, etc.) -- in this case, in Button1_Click -- and then BSExceptionHandler.ProcessException(BSExceptionHandler.GetBSException(ex, BSExceptionHandler.GetThisMethodName)) is called.
What my framework does in ProcessException is to determine the type of reporting configured on the system. This is defaulted to "simple", which means the user gets a very general and minimally-intrusive dialog box indicating a problem has occurred and instructing them to contact the IT department. However, there is an optional registry setting which will set the reporting type to either "verbose" or to "email". I use "verbose" on my development machine, because it includes all the exception info in the dialog box so I don't have to go look at the log. The "email" option is used on servers where I have applications running when there is no user logged on; in that case, the error information is emailed to the IT department to alert them of the issue.
The other thing that happens from here, regardless of the reporting type, is that the error information is recorded to the Windows event log. Here is an example:
SILENT: No
ROOT ASSEMBLY: C:\Users\roryap\AppData\Local\Temporary Projects\WindowsApplication1\bin\Debug\WindowsApplication1.exe
DESCRIPTION: BromsunExceptionHandling.BSException: Calling Method 'WindowsApplication1.Form1.method2()' produced 'System.FormatException' exception with message 'Conversion from string "x" to type 'Integer' is not valid.'.
CALLING METHOD: WindowsApplication1.Form1.method2()
STACK TRACE: at Microsoft.VisualBasic.CompilerServices.Conversions.ToInteger(String Value)
at WindowsApplication1.Form1.method2() in C:\Users\roryap\AppData\Local\Temporary Projects\WindowsApplication1\Form1.vb:line 32
CALL STACK: WindowsApplication1.Form1.method2()
WindowsApplication1.Form1.Method1()
WindowsApplication1.Form1.Button1_Click(sender As System.Object, e As System.EventArgs)
SOURCE: Microsoft.VisualBasic
TARGET SITE: Int32 ToInteger(System.String)
EXTRA INFO:
When the user reports the issue to IT, all IT has to do is check their event log to get the error info. Furthermore, the application does not exit; it continues running because it never allows the exception to bubble up outside of the point where you've chosen to process the exception with the handling framework. Once it's handled by the framework, it's done.
While there are a few downsides to this approach, I have found it to be an extremely robust system and it has saved me many many hours of blind troubleshooting over the years. I have created snippets so that all I have to do is create a try-catch block then type the snippet shortcut -- e.g. "pbs" or "tbs" -- into the catch-block and hit the tab key to populate the appropriate exception handling method. Therefore, it's quite painless to use this framework in every method. I've even modified my VS project templates to always reference and include the framework so I don't have to do that for every new project.
So, regarding the GetThisMethodName() function: this method uses System.Diagnostics.StackTrace, System.Diagnostics.StackFrame, and System.Reflection.MethodBase to figure out the name of the method where the original exception was wrapped inside the BSException.
For me works this solution:
In WebApiConfig.cs add:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Services.Replace(typeof(IExceptionLogger), new UnhandledExceptionLogger());
...
}
Create new file UnhandledExceptionLogger.cs:
public class UnhandledExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
File.AppendAllText("log.txt", context.Exception.ToString());
}
}
I have a class containing something like the following:
public static class Config
{
private static Lazy<ConfigSource> _cfgSrc = new Lazy<ConfigSource>(
() => { /* "ValueFactory" here... */ },
true);
public static ConfigSource ConfigSource
{
get { return _cfgSrc.Value; }
}
}
In accessing the ConfigSource property, I encountered this InvalidOperationException:
ValueFactory attempted to access the Value property of this instance.
I don't see anything in my "value factory" method that accesses the Value property. Is there anything else that could be triggering this exception? This problem only happens intermittently, but once it does, it takes resetting IIS to clear up the Exception (which appears to be cached once it occurs).
It turned out that this error only occurred when trying to inspect the Value property of the Lazy<> in the Visual Studio debugger. Doing so appeared to create a deadlock because the accessing of Value then seemed to hang the thread for a long time until the InvalidOperationException finally occurred. I could never intercept the original Exception, so I couldn't see the inner stacktrace.
I'm just chalking this up as a bug in Visual Studio or their implementation of Lazy<>.
This has also happened to me with circular dependencies, so if these steps lead you nowhere, try double checking the stacktrace and verifying that there are no circular dependencies.
ValueFactory attempted to access the Value property of this instance.
It may help somebody, I was able to fix that error by inspecting my entire ValueFactory procedure.
In my example, I was creating a simple model and the linked it with some other data but during the linking process I was accessing the Value property in a singleton and that caused the error.
So accessing the Value of a Lazy object inside the ValueFactory throws such an error.
As the error message is already indicating ;-)
The behavior of Lazy<T> is to cache exceptions thrown by the ValueFactory. This can lead to potentially confusing behavior due to the paucity of information given in the InvalidOperationException message. Microsoft was made aware of this issue through Connect, however, it is marked as Wont Fix as they feel there is enough information in the exception itself to diagnose the problem.
If there is an inner exception for the IOE you receive, it should (not saying it will) contain enough information to continue onwards. Another possibility is you have a try...catch blocks which rethrows exceptions (throw ex; instead of throw;), you will lose valuable information.
To make sure your exception isn't cached, use LazyThreadSafetyMode.PublicationOnly as a second parameter, instead of true.
Using true, you'll end up with a LazyThreadSafetyMode.ExecutionAndPublication. This will ensure only one thread enteres the ValueFactory method, but also ensures exceptions will be cached.
private static Lazy<ConfigSource> _cfgSrc = new Lazy<ConfigSource>(
() => { /* "ValueFactory" here... */ },
LazyThreadSafetyMode.PublicationOnly);
See the link sixlettervariables provided for more information.
When lazy loading a configuration, be sure to not call methods that need said configuration. This will recall the configuration loader which starts over the process, resulting in the described error.
In my case, I was logging the loadstate, while the logger required a configuration
Take this code:
using System;
namespace OddThrow
{
class Program
{
static void Main(string[] args)
{
try
{
throw new Exception("Exception!");
}
finally
{
System.Threading.Thread.Sleep(2500);
Console.Error.WriteLine("I'm dying!");
System.Threading.Thread.Sleep(2500);
}
}
}
}
Which gives me this output:
Unhandled Exception: System.Exception: Exception!
at OddThrow.Program.Main(String[] args) in C:\Documents and Settings\username
\My Documents\Visual Studio 2008\Projects\OddThrow\OddThrow\Program.cs:line 14
I'm dying!
My question is: why does the unhandled exception text occur before the finally's? In my mind, the finally should be excuted as the stack unwinds, before we even know that this exception is unhandled. Note the calls to Sleep() - these occur after the unhandled exception is printed, as if it was doing this following:
Unhandled exception text/message
Finally blocks.
Terminate application
According to the C# standard, §8.9.5, this behaviour is wrong:
In the current function member, each try statement that encloses the throw point is examined. For each statement S, starting with the innermost try statement and ending with the outermost try statement, the following steps are evaluated:
If the try block of S encloses the throw point and if S has one or more catch clauses, the catch clauses are examined in order of appearance to locate a suitable handler for the exception. The first catch clause that specifies the exception type or a base type of the exception type is considered a match. A general catch clause (§8.10) is considered a match for any exception type. If a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.
Otherwise, if the try block or a catch block of S encloses the throw point and if S has a finally block, control is transferred to the finally block. If the finally block throws another exception, processing of the current exception is terminated. Otherwise, when control reaches the end point of the finally block, processing of the current exception is continued.
If an exception handler was not located in the current function member invocation, the function member invocation is terminated. The steps above are then repeated for the caller of the function member with a throw point corresponding to the statement from which the function member was invoked.
If the exception processing terminates all function member invocations in the current thread, indicating that the thread has no handler for the exception, then the thread is itself terminated. The impact of such termination is implementation-defined.
Where am I going wrong? (I've got some custom console error messages, and this is in-the-way. Minor, just annoying, and making me question the language...)
The standard's statements about the order of execution are correct, and not inconsistent with what you are observing. The "Unhandled exception" message is allowed to appear at any point in the process, because it is just a message from the CLR, not actually an exception handler itself. The rules about order of execution only apply to code being executed inside the CLR, not to what the CLR itself does.
What you've actually done is expose an implementation detail, which is that unhandled exceptions are recognised by looking at a stack of which try{} blocks we are inside, rather than by actually exploring all the way to the root. Exceptions may or may not be handled by looking at this stack, but unhandled exceptions are recognised this way.
As you may be aware, if you put a top-level try{}catch{} in your main function, then you will see the behaviour you expect: each function's finally will be executed before checking the next frame up for a matching catch{}.
I could be way off base in the way I'm reading things...but you have a try finally block without a catch.
Juding by the description you posted, since the Exception is never caught, it bubbles up to the caller, works it's way up through the stack, is eventually unhandled, the call terminates, and then the finally block is called.
The output is actually from the default CLR exception handler. Exception Handlers occur before the finally block. After the finally block the CLR terminates because of the unhandled exception (it can't terminate before, as c# guarantees [1] that the finally clause is called).
So I'd say it's just standard behaviour, exception handling occurs before finally.
[1] guranteed during normal operation at least in absence of internal runtime errors or power outage
To add more into the mix, consider this:
using System;
namespace OddThrow
{
class Program
{
static void Main()
{
AppDomain.CurrentDomain.UnhandledException +=
delegate(object sender, UnhandledExceptionEventArgs e)
{
Console.Out.WriteLine("In AppDomain.UnhandledException");
};
try
{
throw new Exception("Exception!");
}
catch
{
Console.Error.WriteLine("In catch");
throw;
}
finally
{
Console.Error.WriteLine("In finally");
}
}
}
}
Which on my system (Norwegian) shows this:
[C:\..] ConsoleApplication5.exe
In catch
In AppDomain.UnhandledException
Ubehandlet unntak: System.Exception: Exception!
ved OddThrow.Program.Main() i ..\Program.cs:linje 24
In finally
Although not completely expected, the program does behave as it should. A finally block is not expected to be run first, it is only expected to be run always.
I adjusted your sample:
public static void Main()
{
try
{
Console.WriteLine("Before throwing");
throw new Exception("Exception!");
}
finally
{
Console.WriteLine("In finally");
Console.ReadLine();
}
}
In this case you will get the nasty unhandled exception dialog, but afterwards the console will output and wait for input, thus executing the finally, just not before windows itself catches the unhandled exception.
A try/finally without a catch will use the default handler which does exactly what you see. I use it all the time, e.g., in cases where handling the exception would be covering an error but there's still some cleanup you want to do.
Also remember that output to standard error and standard out are buffered.
The try-catch-finally blocks are working exactly as you expected if they are caught at some point. When I wrote a test program for this, and I use various nesting levels, the only case that it behaved in a way that matched what you described was when the exception was completely unhandled by code, and it bubbled out to the operating system.
Each time I ran it, the OS was what created the error message.
So the issue is not with C#, it is with the fact that an error that is unhandled by user code is no longer under the control of the application and therefore the runtime (I believe) cannot force an execution pattern on it.
If you had created a windows form application, and wrote all your messages to a textbox (then immediately flushing them) instead of writing directly to the console, you would not have seen that error message at all, because it was inserted into the error console by the calling application and not by your own code.
EDIT
I'll try to highlight the key part of that. Unhandled exceptions are out of your control, and you cannot determine when their exception handler will be executed. If you catch the exception at some point in your application, then the finally blocks will be executed before the lower-in-the-stack catch block.
To put a couple of answers together, what happens is that as soon as you have a Unhandled Exception a UnhandledExceptionEvent is raised on the AppDomain, then the code continues to execute (i.e. the finally). This is the MSDN Article on the event
Next try:
I believe this case isn't mentioned in the c# standard and I agree it seems to almost contradict it.
I believe the internal reason why this is happening is somewhat like this:
The CLR registers its default exception handler as SEH handler into FS:[0]
when you have more catches in your code, those handlers are added to the SEH chain. Alternatively, only the CLR handler is called during SEH handling and handles the CLR exception chain internally, I don't know which.
In your code when the exception is thrown, only the default handler is in the SEH chain. This handler is called before any stack unrolling begins.
The default exception handler knows that there are no exception handler registered on the stack. Therefore it calls all registered UnhandledException handler first, then prints its error message and marks the AppDomain for unloading.
Only after that stack unrolling even begins and finally blocks are called according the c# standard.
As i see it, the way the CLR handles unhandled exception isn't considered in the c# standard, only the order in which finallys are called during stack unrolling. This order is preserved. After that the "The impact of such termination is implementation-defined." clause takes effect.