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

时间:2012-11-23 00:38:38

标签: c# .net windows service

我开发了32位服务,我在Windows 7 Home Premium x64中运行它。 问题是,当我启动它时,Windows会给我以下消息

  

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

我在事件日志中找到了以下消息

  

无法启动服务。 System.ArgumentException:Log WLConsumer已在本地计算机上注册为源。      在System.Diagnostics.EventLogInternal.CreateEventSource(EventSourceCreationData sourceData)      在System.Diagnostics.EventLogInternal.VerifyAndCreateSource(String sourceName,String currentMachineName)      at System.Diagnostics.EventLogInternal.WriteEntry(String message,EventLogEntryType type,Int32 eventID,Int16 category,Byte [] rawData)      在System.Diagnostics.EventLog.WriteEntry(String message,EventLogEntryType type)      在C:\ Program Files(x86)\ CSI \ WeblogicConsumerService \ WeblogicConsumer.cs中的WeblogicConsumerService.WeblogicConsumer.winEventlogMe(String logTxt,String logSrc,Char entryType):第136行      在WeblogicConsumerService.WeblogicConsumer.OnStart(String [] args)中的C:\ Program Files(x86)\ CSI \ WeblogicConsumerService \ WeblogicConsumer.cs:第63行      在System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(对象状态)

这是我在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()方法显然有问题。 有人可以帮我弄清楚问题是什么,因为我现在完全不知道如何解决这个问题。

预先

thanx:)


@nick_w我已根据您的建议编辑了我的代码,该服务已成功启动。但在停止它时,我得到以下消息:

  

无法停止服务。 System.ArgumentException:源'WLConsumer2012'未在日志'ServiceStop'中注册。 (它在日志'SeriviceStartup'中注册。)“Source和Log属性必须匹配,或者您可以将Log设置为空字符串,它将自动匹配Source属性。      在System.Diagnostics.EventLogInternal.VerifyAndCreateSource(String sourceName,String currentMachineName)      at System.Diagnostics.EventLogInternal.WriteEntry(String message,EventLogEntryType type,Int32 eventID,Int16 category,Byte [] rawData)      在System.Diagnostics.EventLog.WriteEntry(String message,EventLogEntryType type)      在WeblogicConsumerService.WeblogicConsumer.winEventlogMe(String logTxt,String logSrc,Char entryType)中的C:\ Program Files(x86)\ CSI \ WeblogicConsumerService \ WeblogicConsumer.cs:第139行      在C:\ Program Files(x86)\ CSI \ WeblogicConsumerService \ WeblogicConsumer.cs中的WeblogicConsumerService.WeblogicConsumer.OnStop():第70行      在System.ServiceProcess.ServiceBase.DeferredStop()

这是OnStop()方法

        protected override void OnStop()
    {
        winEventlogMe("Successful stop", "ServiceStop", 'i');
    }

这些事件日志开始让我感到困惑。我已经完成了登录其他服务的相同方法,从未遇到过这样的问题。我怎么能在这项服务中得到这些错误,但与我所做的其他所有错误并无太大差别:(

2 个答案:

答案 0 :(得分: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(强调我的):

  

如果您写入事件日志,则必须指定或创建事件源。您必须具有计算机的管理权限才能创建新的事件源。 Source使用事件日志将您的应用程序注册为有效的条目来源。 您一次只能使用Source写入一个日志。 Source可以是任意随机字符串,但名称必须与计算机上的其他来源不同。 源通常是应用程序的名称或其他标识字符串。尝试创建重复的Source值会引发异常。 但是,单个事件日志可以与多个来源相关联。

我建议的是:

使用WLConsumer(或WLConsumer2012)作为您的来源,

  1. 定义您自己的日志,'WLConsumerServiceEventLog`或其他内容;或
  2. 将日志留空。在这种情况下,它们会进入应用程序日志。
  3. 无论如何,标准做法似乎是在第一次运行服务之前做这样的事情,例如在安装程序中(直接从上面的链接复制):

    // 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创建日志。如果您使用安装程序部署服务,这可能是更容易的选择。

答案 1 :(得分:0)

关键是不要重载on start方法并且为了防止服务启动失败,通常onstart方法将主代码作为单独的线程启动