调试windows service的OnStart事件及调试service的一些方法汇总
2010-03-23 14:50
387 查看
关于调试windowsservice,其实这是一个老生常谈的问题了.
通常的处理办法是,在service运行后,在调试器中选择attachtoprocess.
然而这种做法也有一定的局限性,例如在service启动时的OnStart事件中的代码,基本上很难调试.往往当attach到我们的service的时候,这部分代码已经执行过了.于是,有人提出,可以另写一个project来调用这个OnStart方法,或将OnStart方法中的代码搬到另一个project中测试.不过,这些方法终究不是以windows服务的方式调试的,不能够最真实的反应service运行时的执行状况(如权限问题等环境问题).
我的做法是,在OnStart方法的最开始部分加上"Debugger.Launch()"的调用,当service运行到此处时,将会弹出一个选择调试器的对话框,同时暂停在当前位置.这样,我们就做到了在代码中手动的启动调试器.
示例代码如下:
调试WindowsService的OnStart函数是比较困难的也比较让人头疼的事情,用attachprocess的方法是不能调试OnStart函数的,在挂载时就已经执行过了。我在网上看了一些方法都是比较麻烦的,有的说是写一个console程序将OnStart函数里的代码先在console程序里调试通了再放到service中,感觉这个方法工作量太大了,^_^我是比较懒的,后来在网上看到一个很简单的方法是这样的
virtualvoidOnStart(String*args[])
{
Debugger::Launch();
//TODO:Addcodeheretostartyourservice.
}
我试了这个方法后,发现还是不行,我查了msdn说Debugger::Launch()是发动和挂载到相应的进程中,他并没有breadkpoint的功能,我就想啊,要是能动态的加一个breakpoint那问题不是就解决了吗?
virtualvoidOnStart(String*args[])
{
Debugger::Launch();
Debugger::Launch();
//TODO:Addcodeheretostartyourservice.这样就可以跳到这里来调试了
}
可是我们在程序中设置断点后在运行exe文件时是不会break的。既然Debugger有挂载的功能会不会也有动态设置断点的功能呢,^_^,去msdn看了下它的成员函数果然有一个方法Debugger::Break()可以动态设置断点,问题就轻松解决了。^_^。既然Debugger::Break();可以动态设置断点那么在调试windowsService的其他函数中也可以用到,那调试windowsService程序不是和调试winform程序一样简单了吗?^_^
virtualvoidOnStart(String*args[])
中的参数,是在启动服务时可以传入的。
例如:>cmdscstartservicenameargs[0]args[1].........
雖然MSDN的HOWTO:偵錯Windows服務應用程式文件有教如何除錯,但是這樣的除錯有個大缺點,就是有時後程式碼是在OnStart事件一開始的時候就發生問題的,有時後就會因為來不及附加(Attach)程序導致無法除錯。另外,對於「安裝專案」內的「自訂動作」由於是在專案的Installer類別中執行的,所以要對「安裝專案」進行除錯也不太容易。我今天就來分享幾個很簡單又有效的除錯密技。
方法一:透過System.Diagnostics.Debugger.Launch()方法
這個方式我個人是比較喜歡,因為在開發時期要加Code上去很容易,你只要在想要除錯的程式碼之前加上以下程式片段,就可以要求程式暫停,並讓你選用VisualStudio進行除錯!
當執行程式到這行時,就會出現以下視窗:
相對的要對「安裝專案」中的自訂動作除錯,也可以使用這個技巧,方便又有效!
在啟動VisualStudio的Debugger之後,你也可以利用Debugger.Break()方法自訂中斷點,你可以在希望監看的程式碼片段之前加上這個方法,或是透過一些條件判斷讓VisualStudioDebugger執行到這行時自動暫停讓你可以看看當下的物件狀況。
方法二:在OnStart事件開始前先睡個20秒
來不及附加程序的問題要解決也很簡單,「睡」一下就好了,讓程式在睡覺的時候趕緊利用VisualStudio附加該服務的程序。
方法三:把WindowsService當成ConsoleApplication來執行
大家應該知道WindowsService是沒辦法直接按下F5啟動程式的,所以一般的處理方式都是WindowsService專案搭配一個WindowsSetup專案進行安裝,安裝後再啟動,然後再想辦法進行除錯。
但事實上,透過一點點小修改也可以讓WindowsService變成ConsoleApplication來執行,這樣一來你就可以用F5啟動程式並直接進入偵錯模式了!
要達成這個目標,有2件事必須瞭解,瞭解後就知道我在寫什麼了。
1.由於WindowsService與ConsoleAppliation的程式進入點都一樣是staticvoidMain(),預設的Main()內容如下:
2.在WindowsService專案中的啟動點是在OnStart方法,但這個方法是屬於protected存取層級,無法對外公開使用。
---
接下來,就要正式修改程式了,共有3個步驟:
1.先修改Service1.cs程式(WindowsService專案中的主要服務類別)
由於OnStart與OnStop方法被protected宣告保護著,無法讓使用此類別的程式直接呼叫,此時必須多寫兩個方法(method)讓使用此類別的程式可以呼叫OnStart()方法。
2.接著修改Program.cs中的Main()方法(也就是整個WindowsService專案的程式啟動點)
透過Environment.UserInteractive屬性即可得知該組件是執行於使用者互動模式中,若該組件是以WindowsService執行時,則此屬性將會回傳false,我將原本的Main()程式改成以下程式碼:
3.變更WindowsService專案的輸出類型(OutputType)
開啟WindowsService專案屬性(Properties)視窗,將原本的WindowsApplication切換到ConsoleApplication即可。
---
如此一來,你就可以讓同一個組件同時可以用來當WindowsService的主程式,以及可以直接當成Console程式來執行,非常的方便。
Service启动失败,后提示以下错误信息:
查了一下资料,应该是服务的逻辑代码出了问题,打开控制面板/管理工具/事件查看器->应用程序里发现了如下信息:
双击错误信息,即可找到服务的错误提示!~!~
根据错误的提示信息,可检查代码。
通常的处理办法是,在service运行后,在调试器中选择attachtoprocess.
然而这种做法也有一定的局限性,例如在service启动时的OnStart事件中的代码,基本上很难调试.往往当attach到我们的service的时候,这部分代码已经执行过了.于是,有人提出,可以另写一个project来调用这个OnStart方法,或将OnStart方法中的代码搬到另一个project中测试.不过,这些方法终究不是以windows服务的方式调试的,不能够最真实的反应service运行时的执行状况(如权限问题等环境问题).
我的做法是,在OnStart方法的最开始部分加上"Debugger.Launch()"的调用,当service运行到此处时,将会弹出一个选择调试器的对话框,同时暂停在当前位置.这样,我们就做到了在代码中手动的启动调试器.
示例代码如下:
usingSystem.Diagnostics;
publicpartialclassMyService:ServiceBase{
publicMyService(){
InitializeComponent();
}
protectedoverridevoidOnStart(string[]args){
#ifDEBUG
Debugger.Launch();//Launchesandattachesadebuggertotheprocess.
#endif
//TODO:addyourinitializecodehere.
}
protectedoverridevoidOnStop(){
}
}
调试WindowsService的OnStart函数是比较困难的也比较让人头疼的事情,用attachprocess的方法是不能调试OnStart函数的,在挂载时就已经执行过了。我在网上看了一些方法都是比较麻烦的,有的说是写一个console程序将OnStart函数里的代码先在console程序里调试通了再放到service中,感觉这个方法工作量太大了,^_^我是比较懒的,后来在网上看到一个很简单的方法是这样的
virtualvoidOnStart(String*args[])
{
Debugger::Launch();
//TODO:Addcodeheretostartyourservice.
}
我试了这个方法后,发现还是不行,我查了msdn说Debugger::Launch()是发动和挂载到相应的进程中,他并没有breadkpoint的功能,我就想啊,要是能动态的加一个breakpoint那问题不是就解决了吗?
virtualvoidOnStart(String*args[])
{
Debugger::Launch();
Debugger::Launch();
//TODO:Addcodeheretostartyourservice.这样就可以跳到这里来调试了
}
可是我们在程序中设置断点后在运行exe文件时是不会break的。既然Debugger有挂载的功能会不会也有动态设置断点的功能呢,^_^,去msdn看了下它的成员函数果然有一个方法Debugger::Break()可以动态设置断点,问题就轻松解决了。^_^。既然Debugger::Break();可以动态设置断点那么在调试windowsService的其他函数中也可以用到,那调试windowsService程序不是和调试winform程序一样简单了吗?^_^
virtualvoidOnStart(String*args[])
中的参数,是在启动服务时可以传入的。
例如:>cmdscstartservicenameargs[0]args[1].........
如何對[Windows服務]與[安裝專案的自訂動作]進行除錯
雖然MSDN的方法一:透過
這個方式我個人是比較喜歡,因為在開發時期要加Code上去很容易,你只要在想要除錯的程式碼之前加上以下程式片段,就可以要求程式暫停,並讓你選用VisualStudio進行除錯!
System.Diagnostics.Debugger.Launch();
當執行程式到這行時,就會出現以下視窗:
相對的要對「安裝專案」中的自訂動作除錯,也可以使用這個技巧,方便又有效!
在啟動VisualStudio的Debugger之後,你也可以利用
方法二:在OnStart事件開始前先睡個20秒
來不及附加程序的問題要解決也很簡單,「睡」一下就好了,讓程式在睡覺的時候趕緊利用VisualStudio附加該服務的程序。
System.Threading.Thread.Sleep(1000*20);
方法三:把WindowsService當成ConsoleApplication來執行
大家應該知道WindowsService是沒辦法直接按下F5啟動程式的,所以一般的處理方式都是WindowsService專案搭配一個WindowsSetup專案進行安裝,安裝後再啟動,然後再想辦法進行除錯。
但事實上,透過一點點小修改也可以讓WindowsService變成ConsoleApplication來執行,這樣一來你就可以用F5啟動程式並直接進入偵錯模式了!
要達成這個目標,有2件事必須瞭解,瞭解後就知道我在寫什麼了。
1.由於WindowsService與ConsoleAppliation的程式進入點都一樣是staticvoidMain(),預設的Main()內容如下:
staticvoidMain()
{
ServiceBase[]ServicesToRun;
ServicesToRun=newServiceBase[]
{
newService1()
};
ServiceBase.Run(ServicesToRun);
}
2.在WindowsService專案中的啟動點是在OnStart方法,但這個方法是屬於protected存取層級,無法對外公開使用。
---
接下來,就要正式修改程式了,共有3個步驟:
1.先修改Service1.cs程式(WindowsService專案中的主要服務類別)
由於OnStart與OnStop方法被protected宣告保護著,無法讓使用此類別的程式直接呼叫,此時必須多寫兩個方法(method)讓使用此類別的程式可以呼叫
publicvoidStart(string[]args)
{
this.OnStart(args);
}
publicvoidStop()
{
this.OnStop();
}
2.接著修改Program.cs中的Main()方法(也就是整個WindowsService專案的程式啟動點)
透過
staticvoidMain()
{
if(Environment.UserInteractive)
{
Service1s=newService1();
s.Start(null);
Console.WriteLine("服務已啟動,請按下Enter鍵關閉服務...");
//必須要透過Console.ReadLine();先停止程式執行
//因為WindowsService大多是利用多Thread或Timer執行長時間的工作
//所以雖然主執行緒停止執行了,但服務中的執行緒已經在運行了!
Console.ReadLine();
s.Stop();
Console.WriteLine("服務已關閉");
}
else
{
ServiceBase[]ServicesToRun;
ServicesToRun=newServiceBase[]
{
newService1()
};
ServiceBase.Run(ServicesToRun);
}
}
3.變更WindowsService專案的輸出類型(OutputType)
開啟WindowsService專案屬性(Properties)視窗,將原本的WindowsApplication切換到ConsoleApplication即可。
---
如此一來,你就可以讓同一個組件同時可以用來當WindowsService的主程式,以及可以直接當成Console程式來執行,非常的方便。
Service启动失败,后提示以下错误信息:
查了一下资料,应该是服务的逻辑代码出了问题,打开控制面板/管理工具/事件查看器->应用程序里发现了如下信息:
双击错误信息,即可找到服务的错误提示!~!~
根据错误的提示信息,可检查代码。
相关文章推荐
- 调试windows service的OnStart事件.
- 调试windows service的OnStart事件.
- 调试windows service的onstart事件
- .net中调试WindowsService的OnStart()(
- service的onStartCommand方法
- Service的onStartCommand方法空指针错误
- To start or stop dbconsole as a service on Microsoft Windows:
- Android Service的onStartCommand方法返回值作用
- service中onStartCommand方法return介绍和如何创建不被杀死的service
- 调试Windows Service 程序的一些心得
- Android--service里 onstart()onStartCommand()方法的区别
- Service的onStartCommand方法的疑问
- Windows Service 调试方法
- Service的onStartCommand()方法返回值详解
- Android中 Service的onStartCommand方法空指针错误
- Service中onStartCommand方法intent报空的问题
- Android中service的onStartCommand()方法中intent为null的问题
- Service中onStartCommand回调方法的返回值分析
- Android Service生命周期 Service里面的onStartCommand()方法详解
- 调试Windows Service 程序的一些心得