Windows服务自动启动和停止,异常处理问题。

4
我开发了一个32位的服务,并在Windows 7 Home Premium x64上运行它。问题是,当我启动它时,Windows会给我以下消息:
“本地计算机上的WLConsumer服务已经启动,然后停止。某些服务会在其他服务或程序未使用它们时自动停止。”
我在事件日志中找到了以下消息:
“无法启动服务。System.ArgumentException: 日志WLConsumer已在本地计算机上注册为源。 at System.Diagnostics.EventLogInternal.CreateEventSource(EventSourceCreationData sourceData) at System.Diagnostics.EventLogInternal.VerifyAndCreateSource(String sourceName, String currentMachineName) at System.Diagnostics.EventLogInternal.WriteEntry(String message, EventLogEntryType type, Int32 eventID, Int16 category, Byte[] rawData) at System.Diagnostics.EventLog.WriteEntry(String message, EventLogEntryType type) at WeblogicConsumerService.WeblogicConsumer.winEventlogMe(String logTxt, String logSrc, Char entryType) in C:\Program Files (x86)\CSI\WeblogicConsumerService\WeblogicConsumer.cs:line 136 at WeblogicConsumerService.WeblogicConsumer.OnStart(String[] args) in C:\Program Files (x86)\CSI\WeblogicConsumerService\WeblogicConsumer.cs:line 63 at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object state)”
这是OnStart()方法中的代码块:
   protected override void OnStart(string[] args)
    {
        #region WEBLOGIC CREDENTIALS
        try
        {
            //Weblogic URL
            this.url = Registry.LocalMachine.OpenSubKey(@"Software\CSI_WL").GetValue("URL").ToString();

            //Queue name
            this.qName = Registry.LocalMachine.OpenSubKey(@"Software\CSI_WL").GetValue("Queue").ToString();

            //Weblogic login name
            this.user = Registry.LocalMachine.OpenSubKey(@"Software\CSI_WL").GetValue("User").ToString();

            //Weblogic password
            this.pwd = Registry.LocalMachine.OpenSubKey(@"Software\CSI_WL").GetValue("Pwd").ToString();

            //Weblogic Connection Factory
            this.cfName = Registry.LocalMachine.OpenSubKey(@"Software\CSI_WL").GetValue("ConnectionFactory").ToString();

            //root folder
            this.rFolder = Registry.LocalMachine.OpenSubKey(@"Software\CSI_WL").GetValue("root").ToString();
        }
        catch (Exception e)
        {
            winEventlogMe(e.Message, "WLRegistryKeys", 'e');
        }
        #endregion

        winEventlogMe("Successful start", "SeriviceStartup", 'i');
        synchro.Enabled = true;
    }

我调用的方法是winEventLogMe,用于日志记录。

        public static void winEventlogMe(string logTxt, string logSrc, char entryType)
    {
        #region Log
        //Log to event log

        EventLog theEvent = new EventLog("WLConsumer");
        theEvent.Source = logSrc;
        if (entryType == 'e')
            theEvent.WriteEntry(logTxt, EventLogEntryType.Error);
        else if (entryType == 'i')
            theEvent.WriteEntry(logTxt, EventLogEntryType.Information);
        else if (entryType == 'w')
            theEvent.WriteEntry(logTxt, EventLogEntryType.Warning);
        else
            theEvent.WriteEntry(logTxt, EventLogEntryType.Error);*/
        #endregion
    }

当我在OnStart()方法中注释掉winEventLogMe()方法的调用时,服务可以正常启动,所以显然winEventLogMe()方法存在问题。能否有人帮我找出问题所在,因为我现在完全不知道如何解决这个问题。
提前感谢:)
@nick_w 我已按照您的建议编辑了我的代码,服务成功启动。但在停止时,我收到以下消息:
“无法停止服务。System.ArgumentException: The source 'WLConsumer2012' is not registered in log 'ServiceStop'. (It is registered in log 'SeriviceStartup'.) " The Source and Log properties must be matched, or you may set Log to the empty string, and it will automatically be matched to the Source property. at System.Diagnostics.EventLogInternal.VerifyAndCreateSource(String sourceName, String currentMachineName) at System.Diagnostics.EventLogInternal.WriteEntry(String message, EventLogEntryType type, Int32 eventID, Int16 category, Byte[] rawData) at System.Diagnostics.EventLog.WriteEntry(String message, EventLogEntryType type) at WeblogicConsumerService.WeblogicConsumer.winEventlogMe(String logTxt, String logSrc, Char entryType) in C:\Program Files (x86)\CSI\WeblogicConsumerService\WeblogicConsumer.cs:line 139 at WeblogicConsumerService.WeblogicConsumer.OnStop() in C:\Program Files (x86)\CSI\WeblogicConsumerService\WeblogicConsumer.cs:line 70 at System.ServiceProcess.ServiceBase.DeferredStop()
这是OnStop()方法:
        protected override void OnStop()
    {
        winEventlogMe("Successful stop", "ServiceStop", 'i');
    }

这些事件日志开始让我很困惑。我在其他服务中做了相同的记录方法,从来没有遇到过这样的问题。为什么我会在这个服务中出现这些错误,但它与我以前做过的所有其他服务并没有太大区别 :(


如果您仍在解决这个问题,请查看我的最新编辑。 - nick_w
2个回答

4

我认为这是你的问题:

EventLog theEvent = new EventLog("WLConsumer");

根据异常情况,我认为WLConsumer是事件源的名称。这意味着你最好使用以下内容:
EventLog theEvent = new EventLog(logSrc);
theEvent.Source = "WLConsumer";

我只是反过来使用了参数。

如果我进行一些反编译,会有这样一个检查:

if (!EventLogInternal.SourceExists(logName, machineName, true))

在您的情况下,我认为此检查返回 true,这意味着它正在尝试创建一个名为 WLConsumer 的日志,但失败了,因为 WLConsumer 已经注册为事件源。
编辑:
过去我使用事件日志时,将所有数据都写入相同的源和日志中。在您的情况下,每次写入条目时似乎都使用不同的源和日志组合。
来自 MSDN(我强调):
如果您要写入事件日志,则必须指定或创建事件源。您必须在计算机上具有管理员权限才能创建新的事件源。源将您的应用程序注册到事件日志中,作为条目的有效来源。您一次只能使用该源写入一个日志。源可以是任意随机字符串,但名称必须与计算机上的其他源不同。通常源的名称是应用程序名称或其他标识字符串。尝试创建重复的源值会引发异常。但是,单个事件日志可以与多个源相关联。 我建议您使用“WLConsumer”(或“WLConsumer2012”)作为您的源,并且要么
1.定义自己的日志,“WLConsumerServiceEventLog”或其他名称;要么 2.留空日志。在这种情况下,它们进入应用程序日志。
无论如何,在第一次运行服务之前,标准做法似乎是执行此类操作,例如在安装程序中(直接从以上链接复制)。
// Create the source, if it does not already exist. 
if(!EventLog.SourceExists("MySource"))
{
    //An event log source should not be created and immediately used. 
    //There is a latency time to enable the source, it should be created 
    //prior to executing the application that uses the source. 
    //Execute this sample a second time to use the new source.
    EventLog.CreateEventSource("MySource", "MyNewLog");
    Console.WriteLine("CreatedEventSource");
    Console.WriteLine("Exiting, execute the application a second time to use the source.");
    // The source is created.  Exit the application to allow it to be registered. 
    return;
}

请注意注释中关于延迟的点。日志不一定会立即创建,因此编码时需要考虑这一点。您还可以使用EventLogInstaller来创建日志。如果您正在使用安装程序部署服务,则可能是更简单的选择。

注意:仅考虑日志来源的前8个字符,MyLogSource1可以,但创建时MyLogSource2会出错。 - OzBob

0

不要过度加载on start方法,为了防止服务启动失败,通常onstart方法将主要代码作为单独的线程来启动


你的意思是什么?OnStart 在新服务模板中默认被覆盖。我从未尝试更改该部分,因为我从未遇到过任何问题。 - TnashC
有两种活动会导致Windows服务停止,未处理的异常以及超出服务器OnStart方法启动阈值,请参见[链接](http://serverfault.com/questions/111045/how-do-we-avoid-the-30-second-time-limit-on-starting-windows-services) - Mike Beeler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接