我有一项服务,我不知道运行时间,我估计大约7秒。由于某种原因,服务在第一次运行后停止工作,我无法调试它。它一直在服务管理器上说“启动”,我在附加进程窗口找不到它。
当我尝试停止时,停止按钮仅显示一秒钟。即使我按下它,我也会收到一条错误消息“windows无法停止服务'本地计算机上的Splive。服务没有返回错误。这可能是内部Windows错误或内部服务错误。”
处理此问题的最佳方法是什么?
static void Main(string[] args)
{
ServiceBase.Run(new Program());
ServiceController service = new ServiceController();
service.ServiceName = "SpLive";
service.Start();
//Sp objSportingbet = new Sp();
//objSportingbet.getListingsFromSp();
}
public Program()
{
this.ServiceName = "SpLive";
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
objSportingbet.getListingsFromSp();
timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
timer1.Interval = 7000;
timer1.Enabled = true;
timer1.Start();
}
protected override void OnStop()
{
base.OnStop();
timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
timer1.Interval = 7000;
timer1.Enabled = false;
timer1.Start();
}
private void timer1_Elapsed(object sender, EventArgs e)
{
ServiceController service = new ServiceController();
service.ServiceName = "Sp";
if (service.Status == ServiceControllerStatus.Stopped)
{
service.Start();
}
if (service.Status == ServiceControllerStatus.Running)
{
service.Stop();
}
timer1.Stop();
}
private void InitializeComponent()
{
//
// Program
//
this.CanPauseAndContinue = true;
this.CanShutdown = true;
}
答案 0 :(得分:3)
将服务配置为在调试器下启动:http://support.microsoft.com/kb/824344请注意“配置服务以附带WinDbg调试器启动”
添加(现在有相关代码):
在服务关闭之前,static void Main(string[] args) { ServiceBase.Run(new Program()); ServiceController service = new ServiceController(); service.ServiceName = "SpLive"; service.Start();
ServiceBase.Run(instance)
将不会返回,因此您正在运行该服务,然后在它关闭后要求SCM运行该服务...这只会导致混淆。
这个,加上有一个计时器试图反转服务的状态(启动< - >停止),这让我觉得你需要考虑Windows服务的底层流程模型:
当exe只执行一项服务时:
服务启动(在系统启动时,来自用户请求,......):SCM运行已注册的命令行
Main
运行,告诉SCM(通过ServiceBase.Run
)这是什么服务。此必须与步骤1中使用的注册匹配。
传递给ServiceBase.Run
的实例调用了OnStart
。服务应该启动它将执行的活动然后返回(即异步操作,新线程和线程池都没问题;继续调用OnStart
的线程不是)。
当要关闭的信号到达时(来自任何来源)OnStop
被调用。这应该触发停止OnStart
开始(或从那时开始)的所有活动,并等待它们停止然后返回。
服务停止的唯一原因是,如果其他东西(例如它自己的管理API)触发它,但最好是从UI使用SCM。
答案 1 :(得分:3)
理想情况下,您需要调试服务的OnStart
方法以查看正在发生的情况。并且有可能:
protected override void OnStart(string[] args)
{
#if DEBUG
Debugger.Launch();
#endif
...
}
即使服务未标记为桌面互动,也可以使用。
答案 2 :(得分:0)
OnStart和OnStop处理程序有一个固定的时间限制来处理。我不知道停止是如何工作的(它是否等待线程完成..),但对于OnStart,在你的情况下(我知道它是一个旧线程..)我将所有的应用程序代码移动到一个定时器回调并在OnStart函数中设置定时器。我把我的时间设置为大约1分钟。 OnStart将立即退出,满足服务管理员的要求。但是现在你有一个大约一分钟就会启动的线程,这让你有时间将你的进程附加到调试器。显然,在OnStart定时器回调的第一条指令上设置了一个断点。