Question

I have window service which acts as a sync software. I want to add unhanded exception logging on my service, so I modified my program.cs like this:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
    static void Main()
    {
        // Register Unhandled Exception Handler
        AppDomain.CurrentDomain.UnhandledException +=
            new UnhandledExceptionEventHandler(UnhandledExceptionHandler);

        // Run Service
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new Service() 
        };
        ServiceBase.Run(ServicesToRun);
    }

    static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args)
    {
        // Get Exception
        Exception ex = (Exception)args.ExceptionObject;

        // Generate Error
        string ErrorMessage = String.Format(
            "Error: {0}\r\n" +
            "Runtime Terminating: {1}\r\n----- ----- ----- ----- ----- -----\r\n\r\n" +
            "{2}\r\n\r\n####################################\r\n",
                ex.Message,
                args.IsTerminating,
                ex.StackTrace.Trim());

        // Write Error To File
        try
        {
            using (StreamWriter sw = File.AppendText("UnhandledExceptions.log"))
                sw.WriteLine(errorMessage);
        }
        catch { }
    }
}

Then on my Service.cs file, in the OnStart method, I added a throw new Exception("test"); to see if unhanded exceptions are being logged to file as expected.

When I start my service, it stops immediately as expected; however it doesn't seem to be logging the exception to the specified file.

Any idea what I am doing wrong here? Thanks in advance for any help.

Before you ask, my service runs as Local Service and the directory where my service .exe runs from (c:\mysync) already has Local Service added in the security tab with full read/write access.

Was it helpful?

Solution

OnStart is called in Service base class inside try-catch block. If an exception happens on this stage it catches it and just set a status 1 as a result and do not throw it further:

  string[] args = (string[]) state;
  try
  {
    this.OnStart(args);
    .....
  }
  catch (Exception ex)
  {
    this.WriteEventLogEntry(Res.GetString("StartFailed", new object[1]
    {
      (object) ((object) ex).ToString()
    }), EventLogEntryType.Error);
    this.status.currentState = 1;
  }

As a result you can find a record in EventLogs, but you can't catch it as an unhanded domain exception, as there is no such exception.

OTHER TIPS

   using (StreamWriter sw = File.AppendText("UnhandledExceptions.log"))

It is forever a really bad idea to not use full path names for files (like c:\foo\bar.log). Especially in a service, you have very little control over the default directory for your service. Because it is started by the service control manager, not by the user from the command prompt or a desktop shortcut.

So high odds that you are just looking at the wrong file. The real one probably ended up being written to c:\windows\system32 (or syswow64). The operating system directories are normally write protected but that doesn't work for a service, they run with a highly privileged account so can litter the hard drive anywhere.

Always use full path names. Using the EventLog instead is highly recommended.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top