一般Windows Service都是在本机上开发,然后拿到服务器上去部署。部署到服务器上之后,怎么调试是一个问题。我们可以使用日志记录的方式进行调试,在适当的代码之中加入一些记录日志的代码,然后到日志文件中取查看相应的输出结果。但是有时候明明在本机上运行没有问题,把Windows Service部署到服务器上之后,根本启动不了,已启动就会报出Cannot start in a tiem fashion的错误。这样就说明你的代码肯定有问题。服务都没有启动,那么更不会有写出来的日志了,那么我们怎么来服务器上调试呢?
我们可以先把这个Windows Service做成一个Console应用程序。把主要的代码逻辑写入到这个Console应用程序中,然后再代码中适当的地方Log日志代码,而且要有严谨的异常捕捉代码。完成后,把这个Console程序放入到服务器上运行,这时候如果有异常,就能捕捉到,然后写入到日志文件中。如果Console应用程序也无法启动的话,可能是你本机上开发时用的Framework版本与服务器上的版本不一样,可能是服务器上的版本过低导致的。但是这时候是会有提示的,应该能看出来的。
说到异常捕捉,在涉及到多线程的时候,比较费事。如果线程A中有异常捕捉代码,但是线程A中启动了另外的一个线程B,这时没有异常捕捉代码。
//... try { Thread b = new Thread(new ThreadStart(Xmethod)); b.start(); } catch(Exception e) { Log.Info(e.Message); }即使这样try,范围包含了所有的Trhead语句, 但是在这里仍然捕捉不到b线程中的异常,因为这已经不是同一个线程了,线程A的语句是无法捕捉到线程B的异常的。
但是有时候,我们用了第三方的dll,在这个dll中其使用了多线程。我们程序运行的时候,会提示程序出现异常停止。很可能是因为另外启动的线程中出现了问题没有被捕捉到,直接跑到了应用程序顶端,所以程序就停止了。而我们因为是引用的dll,没有源代码,也无法去线程相关的代码中做一些捕获异常的修改。此时,我们可以给我们的程序增加全局的异常捕获代码,当这个应用程序域中的所有没有被捕获的异常在抛出应用程序顶端之前,都会被这里的代码捕获。
static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); //...Code Logic } static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Exception error = (Exception)e.ExceptionObject; Console.WriteLine("MyHandler caught : " + error.Message); }这里举的例子是Console的例子,WinForm等其他类型也有相应的机制。