【问题标题】:Why the Windows Service not call the OnStart method?为什么 Windows 服务不调用 OnStart 方法?
【发布时间】:2021-06-22 15:54:14
【问题描述】:

我创建了一个具有OnStart 方法的Windows 服务应用程序。该方法将从 app.config 文件中读取一个路径,创建一个对象,然后服务将该对象的覆盖 ToString() 方法写入一个带有 StreamWriter 的文件。

当我使用“net start”手动启动此服务时,这是有效的。因此调用了OnStart 方法,创建了对象并将其ToString 方法写入文件。

我将它设置为 Windows 启动时自动运行的服务。 我的问题是,这个OnStart 方法在Windows 启动服务后没有被调用。所以我认为当windows在启动时开始运行服务时,它启动我的服务只是不调用OnStart方法。

有没有人有同样的问题或有人有解决方案?

OnStart 方法:

protected override void OnStart(string[] args)
    {
        filePath = configReader.ReadConfig("FilePath");
        DateEvent dateEvent = new DateEvent(DateTime.Now, TimeLoggerCore.Events.STARTUP.ToString());
        writer.WriteToFile(dateEvent, filePath, true, false);
    }

构造函数:

public TimeLoggerService()
    {
        InitializeComponent();
        configReader = new AppConfigReader();
        writer = new CSVWriter();
    }

程序.cs:

static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[]
        {
            new TimeLoggerService()
        };
        ServiceBase.Run(ServicesToRun);
    }

【问题讨论】:

  • 很难说..这里没有代码..我的onstart代码有效,所以我们需要一些示例代码..尝试一个真正的小型服务,它可以启动并可能在临时文件中创建一个文件..代码会很小
  • 从解决方案中添加代码。
  • 看起来您从未真正运行过您的服务。节目部分有什么
  • 在哪里?因为它是一个服务,它应该处理 OnStart 事件。正如我在使用“net start”运行时所写的那样,该方法被调用。只是当 windows 启动时没有。
  • 在您的项目中应该是一个 program.cs,其中包含服务类并运行。我想知道是否还有其他事情发生。

标签: c# .net windows service


【解决方案1】:

由于您的服务在您尝试使用net.exe start [ServiceName] 从命令行启动它时启动,但在 Windows 启动时无法启动,可能是它在启动过程中遇到异常。

在构建和使用自定义 Windows 服务时需要注意的重要一点是,Windows 事件日志对于跟踪问题非常有帮助。当服务中发生错误时,值得在事件日志中记录该错误。

另一个有助于在 Visual Studio 中调试正在运行的服务的方法是启动服务,然后将 VS 调试器附加到它。

要让一些 Windows 事件日志记录到您的服务中,我建议修改您的服务代码以记录其启动。请注意,我在这里发布的内容是为本论坛简化的——我通常将所有日志记录代码放入一个单独的类中。这样我就可以在我的服务生命周期中使用它。一个重要的注意事项 - 请务必使用适当的名称设置主服务类的 ServiceName 属性 - 这应该在设计时在服务设计器的“属性”窗口中的 Visual Studio 中完成。

private EventLog _eventLog;

/*
 * Use the EventId enumeration to store event IDs that will be written with events
 * to the Windows event log.
 */
enum EventId  
{
    ServiceStarting = 10,
    ServiceStartNormal = 100,
    ServiceStartFailure = 999;
}

protected override void OnStart(string[] args)
{
    try
    {
        // remember the event log
        _eventLog = EventLog;

        // log start
        LogMessage(_eventLog, "Service starting", EventLogEntryType.Information, EventId.ServiceStarting);

        filePath = configReader.ReadConfig("FilePath");
        DateEvent dateEvent = new DateEvent(DateTime.Now, TimeLoggerCore.Events.STARTUP.ToString());
        writer.WriteToFile(dateEvent, filePath, true, false);

        LogMessage(_eventLog, "Service started", EventLogEntryType.Information, EventId.ServiceStartNormal);
    }
    catch(Exception e)
    {
        LogMessage(_eventLog, e.ToString(), EventLogEntryType.Error, EventId.ServiceStartFailure);
    }
}

private static void LogMessage(EventLog eventLog, string message, EventLogEntryType entryType, EventId eventId)
{
    /*
     * If the event source we want to log doesn't exist, create it.
     * Note that this take admin privs, and creating the log source should be
     * done during service installation.  This is here as a secondary means
     * to create the log in the event that it doesn't already exist.
     */
    if (!EventLog.SourceExists(eventLog.Source)
    {
        EventLog.CreateEventSource(eventLog.Source, eventLog.Log);
    }
    eventLog.WriteEntry(message, entryType, (int) eventId);
}

将此代码添加到您的服务后,重新部署它,重新启动系统,然后检查事件日志。至少您应该会在服务启动时看到一条记录的消息。

【讨论】:

    【解决方案2】:

    我的服务也遇到了同样的问题,经过大量挖掘后,我发现没有调用 OnStop 和 OnStart 的原因是因为 windows 快速启动选项。 我把所有可以被覆盖的 ServiceBase 函数的日志都写进去了,当我关闭笔记本电脑时调用的是 OnPowerEvent,而不是 OnStop。

    My event log

    当我重新启动窗口而不是关闭它们时,一切都按预期工作。

    希望这会对某人有所帮助。

    【讨论】:

      【解决方案3】:

      如果事件查看器显示服务已成功启动,则您的 OnStart 已被调用并已从中返回。你是如何确定 is 没有被调用的?我猜是因为您的文件尚未被写入。问题可能不是您的 OnStart 没有被调用,而是 WriteToFile 失败和/或它被写入了不同的位置(例如,您使用了在启动期间不同或不可用的相对路径)。我建议使用以下程序来检查:

      • 使用 System.Diagnostics.Trace.WriteLine 在 OnStart 中输出调试消息
      • 从 Microsoft 下载并安装/复制 DebugView 应用程序。
      • 将 DebugView 配置为 1) 捕获全局 Win32,2) 使用您的应用程序名称设置进程名称过滤器,以及 3) 在启动时启用日志记录(请参阅 DebugView 帮助)。

      对所有设置进行一些实验,以确保它们按预期工作。

      最后,还要注意OnStart documentation中的这句话:

      不要使用构造函数来执行应该在 OnStart 中的处理。使用 OnStart 处理服务的所有初始化。构造函数在应用程序的可执行文件运行时调用,而不是在服务运行时调用。可执行文件在 OnStart 之前运行。例如,当您继续时,不会再次调用构造函数,因为 SCM 已将对象保存在内存中。如果 OnStop 释放在构造函数中而不是在 OnStart 中分配的资源,则在第二次调用服务时不会再次创建所需的资源。

      【讨论】:

        【解决方案4】:

        正如您提到的 Windows 启动时,您是否将可执行文件放在启动文件夹中?如果是,那将不会那样工作。您需要在 Windows 服务管理器中安装该服务。 Microsoft Description for installing services

        【讨论】:

        • 它说它是 Windows 服务.. 这无关紧要
        • 是的。我忘了提到,我从“VS 2017 的开发人员命令提示符”安装了该服务。我以管理员权限运行这个 cmd。我还可以在管理控制台的“服务”选项卡下看到该服务。
        猜你喜欢
        • 1970-01-01
        • 2014-05-25
        • 2014-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多