C# Windows 服务 - 自动启动然后停止

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7368655/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:02:43  来源:igfitidea点击:

C# Windows Service - Started and then Stopped Automatically

c#.netwindowsservice

提问by Invaderleige

I am creating this windows service by following the instructions at MSDN Walkthrough: Creating a Windows Serviceand after successful installation, I go to Services.msc to Start the Windows service and before it finishes starting up I get the following message:

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

The EIWindowsService service on Local Computer started and then stopped. Some services stop automatically if they are not in use by other services or programs.

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

I know the Windows Service starts ok because there is an entry to the log file stating that the service started. I did some research before posting on here and the answer from Some Services Stop Automaticallystates that the problem could either be that the OnStart method is throwing an error, or that the OnStart is not kicking off a thread. So I modified my code so that the only thing within the OnStart is the starting of two timers and the log entry therefore needing no exception handling. I also added a thread to "jump" to another method.

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

I tried the windows service again and I know that it "moved" to the new method that the thread pointed to because I had a log entry in there that threw aFormatException error due to some conversion I was doing. I commented out the conversion and the windows service still just began to start up and then stopped automatically.

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

Further research indicated to me that I might need a loop to keep the processing within the method, so I took information from C - Windows Service the service onand set up an infinite while loop. I also found that there might be Garbage Collection going on and established a KeepAlive statement for the timers as suggested in Examples section of MSDN Timer Class. Still the same issues.

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

At this point I feel I've exhaused all the research I can do so it would be appropriate to post my question here. All my code is below and I will note that before I performed any change I uninstalled the Windows Service, removed the Setup Project, and deleted the installers from the C# code. I then made changes and started back over with the instructions in the Walkthrough starting at the point where it instructs how to setup the installers. I did this each time because I found that if I made changes and did not uninstall the Windows Service, remove the Setup Project, and delete the installers, then my changes would not take effect on the currently installed windows service.

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

Any assistance you can give would be most appreciated. I will be here for another 15min and then I will check this first thing tomorrow.

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

SERVICE1.cs

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(the relavant stuff)

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;

采纳答案by alf

You don't need to create a separate thread or worry about the garbage collector. The framework handles all that for you. Just create the timers and they will be called. Here's an example.

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

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()
    {
    }
}

回答by Shane Haw

Something else that may help someone coming across this post and the above solutions do not work. When I had this problem, I had added this to the config of my Windows Service:

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

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

I added this so that I could attach the debugger to the service when running it locally, however when I tried to move the service to another server it gave the specified error. By removing this from the config the service worked again.

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