【问题标题】:C# Windows Service - Started and then Stopped AutomaticallyC# Windows 服务 - 自动启动然后停止
【发布时间】:2011-11-14 04:22:28
【问题描述】:

我正在按照MSDN Walkthrough: Creating a Windows Service 的说明创建此 Windows 服务,成功安装后,我转到 Services.msc 以启动 Windows 服务,在它完成启动之前我收到以下消息:

本地计算机上的 EIWindowsService 服务启动然后停止。如果某些服务没有被其他服务或程序使用,它们会自动停止。

我知道 Windows 服务可以正常启动,因为日志文件中有一个条目表明该服务已启动。我在这里发帖之前做了一些研究,Some Services Stop Automatically 的回答指出问题可能是 OnStart 方法抛出错误,或者 OnStart 没有启动线程。所以我修改了我的代码,以便 OnStart 中唯一的事情是启动两个计时器和日志条目,因此不需要异常处理。我还添加了一个线程来“跳转”到另一种方法。

我再次尝试了 Windows 服务,我知道它“移动”到了线程指向的新方法,因为我在那里有一个日志条目,由于我正在进行的一些转换而引发了 aFormatException 错误。我把转换注释掉了,windows服务还是刚启动就自动停止了。

进一步的研究表明,我可能需要一个循环来保持方法内的处理,所以我从C - Windows Service the service on 获取信息并设置了一个无限循环。我还发现可能正在进行垃圾收集,并按照MSDN Timer Class 的示例部分中的建议为计时器建立了 KeepAlive 语句。还是一样的问题。

在这一点上,我觉得我已经用尽了所有可以做的研究,所以在这里发布我的问题是合适的。我的所有代码都在下面,我会注意到,在执行任何更改之前,我卸载了 Windows 服务,删除了安装项目,并从 C# 代码中删除了安装程序。然后我进行了更改,并从演练中的说明重新开始,从它指示如何设置安装程序的地方开始。我每次都这样做是因为我发现如果我做了更改并且没有卸载 Windows 服务、删除安装项目并删除安装程序,那么我的更改不会对当前安装的 Windows 服务生效。

您能提供的任何帮助将不胜感激。我将在这里再呆 15 分钟,然后我会在明天检查第一件事。

SERVICE1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Timers;

namespace EIWindowsService
{
    public partial class Service1 : ServiceBase
    {
        Logs.ErrorLog logFile = new Logs.ErrorLog();
        private System.Threading.Thread onStartThread;

        public Service1()
        {
            InitializeComponent();            
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                iTimer.Start();
                iTimer.Elapsed += new ElapsedEventHandler(iTimer_Elapsed);
                pTimer.Start();
                pTimer.Elapsed += new ElapsedEventHandler(pTimer_Elapsed);                
                onStartThread = new System.Threading.Thread(TimerValue);
                onStartThread.Start();
                logFile.SendToLog("EIWindows Service started on " + GetDate());
            }
            catch (ArgumentOutOfRangeException ex)
            {
                logFile.SendToLog("ArgumentOutOfRangeException", "EIWindowsService\\Service1.cs", "OnStart()", ex);
            } //end of ArgumentOutOfRangeException CATCH statement
        }

        protected override void OnStop()
        {
            iTimer.Stop();
            pTimer.Stop();
            logFile.SendToLog("EIWindowsService\\Service1.cs", "OnStop()", "EIWindows Service stopped on " + GetDate());

        }

        private void TimerValue()
        {
            try
            {
                   /*commented out because it was throwing an exception error*/
                   //double iTimerValue = Convert.ToDouble(iTimer.ToString());
                   //double pTimerValue = Convert.ToDouble(pTimer.ToString());
                while (1 > 0)
                {
                       //if (iTimerValue % 1800000 == 0)  //if the timer hits the 30min mark
                       //{
                       //    logFile.SendToLog("Current iTimer Value = " + iTimerValue.ToString());
                       //}
                       //if (pTimerValue % 1800000 == 0)  //if the timer hits the 30min mark
                       //{
                       //    logFile.SendToLog("Current pTimer Value = " + pTimerValue.ToString());
                       //}
                    GC.KeepAlive(iTimer);
                    GC.KeepAlive(pTimer);
                }
                   //TimerValue();
            }
            catch (OverflowException ex)
            {
                logFile.SendToLog("OverflowException", "EIWindowsService\\Service1.cs", "TimerValue()", ex);
            } //end of OverflowException CATCH statement
            catch (ArgumentException ex)
            {
                logFile.SendToLog("ArgumentException", "EIWindowsService\\Service1.cs", "TimerValue()", ex);
            } //end of ArgumentException CATCH statement
            catch (FormatException ex)
            {
                logFile.SendToLog("FormatException", "EIWindowsService\\Service1.cs", "TimerValue()", ex);
            } //end of FormatException CATCH statement
        }

        private string GetDate()
        {
            string current = "No Date Recorded";
            try
            {
                current = DateTime.Now.ToString("F");
            }
            catch (FormatException ex)
            {
                logFile.SendToLog("FormatException", "EIWindowsService\\Service1.cs", "GetDate()", ex);
            } //end of FormatException CATCH statement

            return current;
        } //end of method GetDate

        private void iTimer_Elapsed(object source, ElapsedEventArgs e)
        {
            try
            {
                iTimer.Stop();
                ImportI();
                iTimer.Start();
            }
            catch (ArgumentOutOfRangeException ex)
            {
                logFile.SendToLog("ArgumentOutOfRangeException", "EIWindowsService\\Service1.cs", "iTimer_Elapsed()", ex);
            } //end of ArgumentOutOfRangeException CATCH statement
        } //end of method iTimer_Elapsed

        private void pTimer_Elapsed(object source, ElapsedEventArgs e)
        {
            try
            {
                pTimer.Stop();
                ImportP();
                pTimer.Start();
            }
            catch (ArgumentOutOfRangeException ex)
            {
                logFile.SendToLog("ArgumentOutOfRangeException", "EIWindowsService\\Service1.cs", "pTimer_Elapsed()", ex);
            } //end of ArgumentOutOfRangeException CATCH statement
        } //end of method pTimer_Elapsed

        private void ImportI()
        {
            //does some action but commented out because it never gets here and is not relavant to this question.
        } //end of method ImportI

        private void ImportP()
        {
            //does some action but commented out because it never gets here and is not relavant to this question.
        } //end of method ImportP
    }
}

SERVICE1.DESIGNER.CS(相关的东西)

private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.pTimer = new System.Timers.Timer(10800000);  //3hrs
            this.iTimer = new System.Timers.Timer(3600000);  //1hr
            // 
            // pTimer
            // 
            this.pTimer.Enabled = true;
            // 
            // iTimer
            // 
            this.iTimer.Enabled = true;
            // 
            // Service1
            // 
            this.ServiceName = "EIWindowsService";

        }

        #endregion

        private System.Timers.Timer pTimer;
        private System.Timers.Timer iTimer;

【问题讨论】:

    标签: c# .net windows service


    【解决方案1】:

    您无需创建单独的线程或担心垃圾收集器。该框架为您处理所有这些。只需创建计时器,它们就会被调用。这是一个例子。

    public partial class Service1 : ServiceBase
    {
        private Timer timer;
    
        public Service1()
        {
            InitializeComponent();
        }
    
        protected override void OnStart(string[] args)
        {
            timer = new Timer(1000);
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            timer.Start();
        }
    
        void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            using (StreamWriter writer = File.AppendText(@"C:\Users\alfonso\Desktop\log.txt"))
            {
                writer.WriteLine(string.Format("{0} : {1}", DateTime.Now, "Logging from the service"));
            }
        }
    
        protected override void OnStop()
        {
        }
    }
    

    【讨论】:

    • Alfonso,非常感谢您的回复,但我的问题不是计时器无法正常工作,而是某些“未”发生导致 Windows 认为该服务未在使用中,因此它会自动停止它。现在我确实注意到,不是像我一样在 Service1.Designer.cs 中的 InitializeComponent 方法中定义计时器,而是将它设置为 Service1 类中的全局变量。这可能是我的问题吗?难道仅仅是我需要将计时器更改为全局变量吗?我会测试一下并告诉你。
    • 不,我认为这不是问题所在。也许您的 OnStart 方法中的某些内容引发了异常,并且由于您只处理 ArgumentOutOfRange 异常,因此服务正在终止。
    • Alfonso,因此,对于我的 OnStart 仅处理 ArgumentOutOfRange 异常的评论,我对所有语句进行了一般异常处理,并发现错误是从我的日志文件中抛出的。所以看来这个问题已经解决了。感谢您的帮助。
    【解决方案2】:

    其他可能会帮助遇到此帖子的人的其他方法和上述解决方案不起作用。当我遇到这个问题时,我已将其添加到我的 Windows 服务的配置中:

    <system.web>
        <compilation debug ="true" />    
    </system.web>
    

    我添加了这个,以便在本地运行时将调试器附加到服务,但是当我尝试将服务移动到另一台服务器时,它给出了指定的错误。通过从配置中删除它,服务再次工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多