I'm calling the following from my entry point static main method:
try { ServiceBase.Run(new MonitorSer()); }
catch (Exception ex) { Console.WriteLine(ex.Message + Process.GetCurrentProcess().MainModule.FileName); }
MonitorSer is an instance of:
class MonitorSer : ServiceBase {
and the entry main method is a member of my class:
[RunInstaller(true)]
public class WindowsServiceInstaller : Installer {
I've had good results catching exceptions for debugging but sometimes they seem to find their own way around my traps, as in this case.
I get a windows box flash up telling me I need to install using installutil when what I really want is to find the name of this process and call it again with the -i switch which I have wired up to make it install intself (credit to those here who contributed/recycled that code).
What makes this more frustrating is that if I set breakpoints upto (or on) the call to ServiceBase.Run, it will fail silently and I am left with the bl开发者_JS百科inking console.
UPDATE
static void Install(bool undo, string[] args)
{
try
{
Console.WriteLine(undo ? "uninstalling" : "installing");
using (AssemblyInstaller inst = new AssemblyInstaller(typeof(MonitorSer).Assembly, args))
{
IDictionary state = new Hashtable();
inst.UseNewContext = true;
try
{
if (undo) inst.Uninstall(state);
else
{
inst.Install(state);
inst.Commit(state);
}
}
catch
{
try
{
inst.Rollback(state);
}
catch { }
throw;
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
I clumped the entry point here so I could call the above function, I'll try moving that to another class and setting the entry point there, but I know I can make this entry point (that you, Dmitry, deny) work by calling itself with the appropriate argument to install- which only the BaseService class can do- correct me if I am wrong.
[RunInstaller(true)]
public class WindowsServiceInstaller : Installer
Is not your entry point. This will get called once when you install your service using InstallUtil.exe. Entry point can be specified in the project properties and it usually defaults to Program.Main
. You should not be starting your service from Installer class.
CLR will let you know of unhandled exceptions if you subscribe to this event:
static void Main() {
...
AppDomain.CurrentDomain.UnhandledException
+= CurrentDomain_UnhandledException;
...
}
private static void CurrentDomain_UnhandledException(
Object sender,
UnhandledExceptionEventArgs e) {
if (e != null && e.ExceptionObject != null) {
// log exception:
}
}
This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application ... Starting with the .NET Framework version 4, this event is not raised for exceptions that corrupt the state of the process, such as stack overflows or access violations, unless the event handler is security-critical and has the HandleProcessCorruptedStateExceptionsAttribute attribute. application.
Another place where you might want to log exceptions in windows service (because .NET/SCM will swallow startup exceptions):
protected override void OnStart(String[] args) {
try {
} catch(Exception e) {
// log exception:
throw;
}
}
精彩评论