How can I set up .NET UnhandledException handling in a Windows service? - c#

protected override void OnStart(string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Thread.Sleep(10000);
throw new Exception();
}
void CurrentDomain_UnhandledException(object sender,
UnhandledExceptionEventArgs e)
{
}
I attached a debugger to the above code in my windows service, setting a breakpoint in CurrentDomain_UnhandledException, but it was never hit. The exception pops up saying that it is unhandled, and then the service stops. I even tried putting some code in the event handler, in case it was getting optimized away.
Is this not the proper way to set up unhandled exception handling in a windows service?

The reason that the UnhandledException event on the current AppDomain does not fire is how services are executed.
User sends a Start command from the Windows Service Control Manager (SCM).
The command is received by the framework's ServiceBase implementation and dispatched to the OnStart method.
The OnStart method is called.
Any exception which is thrown by OnStart is handled in the base class, logged to the Event Log, and translated into an error status code returned to the SCM. So the exception never propagates to the AppDomain's unhandled exception handler.
I think you would find that an unhandled exception thrown from a worker thread in your service would be caught by the AppDomain's unhandled exception handler.

In a Windows Service you do NOT want to be running much code in the OnStart method. All you want there is the code to launch your service thread and then return.
If you do that you can handle exceptions that happen in your service thread just fine.
e.g.
public static void Start()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);
running = true;
ThreadStart ts = new ThreadStart(ServiceThreadBody);
thread = new Thread(ts);
thread.Name = "ServiceThread";
thread.Priority = ThreadPriority.BelowNormal;
thread.Start();
}

When I was working on my own Windows Service, it was stoping itself oddly enough. I thought it was because of unhanded exception. At the moment I am catching unhanded exceptions on text file. First of all you have to create new file ServiceLog.txt on C locations due to logging excaptions on text file. With below coding I got all unhanded exceptions with them line numbers.
using System.Security.Permissions;
using System.IO;
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
protected override void OnStart(string[] args)
{ AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
...
Your codes...
....
}
void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
WriteToFile("Simple Service Error on: {0} " + e.Message + e.StackTrace);
}
private void WriteToFile(string text)
{
string path = "C:\\ServiceLog.txt";
using (StreamWriter writer = new StreamWriter(path, true))
{
writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
writer.Close();
}
}

Know this thread is a bit old, but thought it would be useful to add some comments based on personal experience developing Windows services in .NET. The best approach is to avoid developing under the Service Control Manager as much as you can - for this you need a simple harness that mimics the way services get started - something that can create an instance of your service class (that you already derived from ServiceBase) and call your OnStart, OnStop etc methods. This harness can be a console app or a Windows app as you desire.
This is pretty much the only way I have found of debugging service start-up issues in .NET - the interaction between your code, Visual Studio and the real Service Control Manager just makes the process impossible otherwise.
HTH.

Just curious, what are you trying to accomplish: avoiding service crashing, or reporting errors?
For reporting, I think your best bet is to add top-level try/catch statements. You can try to log them to the Windows event log and/or a log file.
You can also set the ExitCode property to a non-zero value until you successfully stop the service. If the system administrator starts your service from the Services control panel, and your service stops suddenly with a non-zero exit code, Windows can show an error message with the description of the error.

Related

How to crash to get "Subsequent failures" of Windows Service Recovery to be considered

We have a Windows service written in C# that starts basically a Web API on a certain port. The service is configured to be restarted on the first failure and the second failure. The "Subsequent failures" is set to "Take No Action".
In case this port might be taken the service crashes with an unhandled exception and in our unhandled exception callback we write dump files to a certain application directory. For whatever reason Windows keeps restarting the service over and over even though it crashed already multiple times. The structure of our service is like this:
public class WinService : ServiceBase
{
private WebApiHostWrapper _apiHost;
private Thread _workerThread;
public WinService()
{
InitializeComponent();
ServiceName = "MyService";
// register handler for writing dumpfiles
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptions.DomainUnhandledException;
}
protected override void OnStart(string[] args)
{
_workerThread = new Thread(InternalStart) { Name = "StartupThread" };
_workerThread.Start(args);
}
private void InternalStart(object args)
{
if (null == _service)
{
Thread.MemoryBarrier();
_apiHost= new WebApiHostWrapper();
_apiHost.Start((string[])args); // exception here
}
}
protected override void OnStop()
{
if (null != _workerThread)
{
_apiHost.Dispose();
_apiHost= null;
if (!_workerThread.Join(5000))
{
_workerThread.Abort();
}
Thread.MemoryBarrier();
_workerThread = null;
}
}
In the Windows event log I see 4 entries.
Service started successfully. (source: MyService)
Applicatio .... stacktrace etc. (source: .NET Runtime)
Faulting application name... dll and exe name (source: Application Error)
Fault bucket, type 0.... (source: Windows Error Reporting)
In a scenario where the port is already in use, this causes the service to crash over and over, flooding the system with dump files. Windows will always restart the service independent from the settings. Is there a special way how to crash in order to get the the "Subsequent Failures" to be considered and NOT to restart the service?
I found the problem that caused only the "First failure" to be executed. We had the "Reset fail count after" set to 0 days. After setting this value to 1 the service crashed 2 times and then was not restarted anymore.
Sources:
https://social.technet.microsoft.com/Forums/windows/en-US/3db76753-4607-4a20-97a0-790c73e379cc/the-actions-after-system-service-failure?forum=winserver8gen
Clarification on Windows Service Recovery Actions Settings
http://www.happysysadm.com/2011/12/understanding-windows-services-recovery.html

How do I gracefully handle this exception in a background thread in a Windows service?

I'm using C# .NET 4.0.
I have a Windows service. This Windows service spins up a background thread. This background thread makes P/Invoke calls to a Win32 API, and very intermittently (on the order of once or twice in a 24 hour period with 1-second intervals,) the Win32 function will return garbage. I do my best to try and handle this garbage without raising an exception, but eventually an exception will occur anyway. And when it does, it terminates my service even though I am using a try/catch that catches the exception.
using System.Security.Principal;
Thread awesomeThread;
protected override void OnStart(string[] args)
{
ThreadStart awesomeThreadThreadStart = new ThreadStart(AwesomeThread);
awesomeThread = new Thread(awesomeThreadThreadStart);
awesomeThread.IsBackground = true;
awesomeThread.Start();
}
private void AwesomeThread()
{
while (serviceStarted)
{
if (serviceStarted)
Thread.Sleep(1000)
else
break;
//
// WinApi calls happen here. Once every few hours, they return gibberish.
//
NTAccount account = new NTAccount(domain, username);
SecurityIdentifier sid = null;
try
{
sid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
}
catch (Exception ex)
{
Eventlog.WriteEntry("Oh no an exception occurred: " + ex.Message);
}
// Resource cleanup stuff
}
}
So when an exception does occur on account.Translate(), the exception is caught and the event log message is written at which point it would be safe for the thread to continue executing... but .NET kills it, and thus, my service. Can I handle the exception and allow the background thread to keep executing?
Currently, as a workaround I have set the Windows service to automatically restart itself in the Service Controller, so I can deal with the service restarting itself once or twice a day, but I'd rather prevent it if I could.
This isn't really an answer, more a comment, but I hate the poor formatting of code in comments.
Are you 100% sure the exception in that one statement is your only problem? I'm suggesting you add the following to your program:
// Create AppDomain ProcessExit and UnhandledException event handlers
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
and, of course, the event handlers:
/// <summary>
/// Method called when the process is exiting.
/// </summary>
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
// do some logging?
}
/// <summary>
/// Method called if an unhandled AppDomain exception occurs.
/// </summary>
private static void CurrentDomain_UnhandledException(object sender,
UnhandledExceptionEventArgs e)
{
// do some logging?
}
You can't save the service at this point, but you might get some useful information.
Edit:
Just noticed I copy-and-pasted some code where the event handlers are marked "static", but that isn't necessary.
Check the Windows Event Log to see if there are any errors reported by .NET at the time the process exits. That will often provides useful info about why a process died.

How to catch exceptions for objects defined in XAML in WPF

Is there a way to catch Exceptions from Objects declared in XAML such as a StoryBoard and keep the application from crashing completely?
In this particular case users will rarely encounter an exception relating to an un-animatable or unaccessible property path. I am working to address these issues but in general the app is critical and I would like to prevent it from simply crashing in these instances.
The app is a UserControl that is Hosted in a windows forms app via ElementHost.
How do you handle these types of exceptions and keep the app running?
Some additional info
I tried using something like:
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
as a means of catching the exceptions but Application.Current is always null so I can't use it.
In a nutshell I need to ensure that no matter what happens the app itself continues to run.
Oh the horror when you get xaml related crash errors! :) I don't have the full receipt in my head here right now, and I need more information about your issue, but make sure to hook on to all following error handlers(App.xaml.cs in WPF, check link below for forms).
DispatcherUnhandledException += UnhandledDispatcherException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
private void UnhandledDispatcherException(Object sender, DispatcherUnhandledExceptionEventArgs e)
{
// do your stuff here!
e.Handled = true; // Ex is now handled and will not crash your app
}
This one is forms only I think(dont have my devbox here).
Application.ThreadException += UnhandledThreadException
Add your handlers and log/System.Diagnostics.Trace.WriteLine/breakpoint away!
Check this example from MSDN regarding AppDomain. Verify that AppDomain.Current is not null when starting as well.
Snippet:
public class Example
{
[SecurityPermission(SecurityAction.Demand,Flags=SecurityPermissionFlag.ControlAppDomain)]
public static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
...
}
}
You may also do this after your InitializeComponents, if Application.Current is null.
if (System.Windows.Application.Current == null)
new System.Windows.Application();
And ofc check your debug output! :)
Hope it helps,
Cheers
Stian

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.

NLog configured to automatically log all exceptions?

Is there a way to configure NLog to automatically log all exceptions my application can send? Currently I am going to all TRY/CATCH blocks and manually adding logging in the CATCH - but what if I miss some? And what if in the future someone else does
Is there a way to tell NLog to just always log all exceptions? Esspecially some that are not caught and could cause a popup?
As far as I know, there is no way to confineNLog to log all exceptions.
If all you want is to log unhandled exceptions, you could add an "UnhandledException Handler" to the AppDomain when initializing your application.
Note that under some circumstances it may not be possible to log the error (e.g. in case of an OutOfMemory exception or something terrible).
Note that the AppDomain also has a FirstChanceException event you can subscribe to, but this would mean that you get notified about every exception that occurs (and may be handled by the usercode) - in this are many.
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomain_CurrentDomain_UnhandledException);
static void AppDomain_CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// use logger here to log the events exception object
// before the application quits
}
Note that this will only allow you to log exceptions that cause your application to crash - you cannot prevent it to crash (therefore the name: unhandled exception).
Another option would be to use Aspect Oriented Programming (AOP) - and introduce a Logging aspect after each method call, in case of an error. If your application uses a Layered architecture, this may be relatively easy to do (e.g. add an aspect to all calls of your business logic layer...).
You may find a framework like PostSharp or Spring.Net useful (usually their websites provide some easy examples for that).
For WebApi application you can do this in Global.asax.cs like that
protected void Application_Error()
{
Exception lastException = Server.GetLastError();
NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
logger.Fatal(lastException);
}
MSDN resource
Jacek's answer is good for WebApi.
Here is an answer for console apps:
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomain_CurrentDomain_UnhandledException);
Object o = SomeMethodToThrowError(); // Cause an exception
}
static void AppDomain_CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// use logger here to log the events exception object
// before the application quits
Exception ex = (Exception)e.ExceptionObject;
Logger.Error(ex.Message + " " + ex.StackTrace);
}

Categories

Resources