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



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

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

我在事件日志中发现以下消息

无法启动服务。System.ArgumentException:日志WLConsumer已在本地计算机上注册为源。位于System.Diagnostics.EventLogInternal.CreateEventSource(EventSourceCreationData sourceData)位于System.Diagnostics.EventLogInternal.VerifyAndCreateSource(字符串sourceName,字符串currentMachineName)在System.Diagnostics.EventLogInternal.WriteEntry(字符串消息,EventLogEntryType类型,Int32事件ID,Int16类别,Byte[]原始数据)位于System.Diagnostics.EventLog.WriteEntry(字符串消息,EventLogEntryType类型)在C:\Program Files(x86)\CSI\WeblogicConsumerService\WeblogicSconsumer.cs:line 136位于C:\Program Files(x86)\CSI\WeblogicConsumerService\WeblogicSconsumer.cs:line 63中的Weblogic ConsumerService.WeblogicConsumer.OnStart(String[]args)在System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(对象状态)

这是我在OnStart()方法中的代码块

protected override void OnStart(string[] args)
{
#region WEBLOGIC CREDENTIALS
try
{
//Weblogic URL
this.url = Registry.LocalMachine.OpenSubKey(@"SoftwareCSI_WL").GetValue("URL").ToString();
//Queue name
this.qName = Registry.LocalMachine.OpenSubKey(@"SoftwareCSI_WL").GetValue("Queue").ToString();
//Weblogic login name
this.user = Registry.LocalMachine.OpenSubKey(@"SoftwareCSI_WL").GetValue("User").ToString();
//Weblogic password
this.pwd = Registry.LocalMachine.OpenSubKey(@"SoftwareCSI_WL").GetValue("Pwd").ToString();
//Weblogic Connection Factory
this.cfName = Registry.LocalMachine.OpenSubKey(@"SoftwareCSI_WL").GetValue("ConnectionFactory").ToString();
//root folder
this.rFolder = Registry.LocalMachine.OpenSubKey(@"SoftwareCSI_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"中注册。(它在日志"ServiceStartup"中注册。)"Source和log属性必须匹配,或者您可以将log设置为空字符串,它将自动与Source属性匹配。位于System.Diagnostics.EventLogInternal.VerifyAndCreateSource(字符串sourceName,字符串currentMachineName)在System.Diagnostics.EventLogInternal.WriteEntry(字符串消息,EventLogEntryType类型,Int32事件ID,Int16类别,Byte[]原始数据)位于System.Diagnostics.EventLog.WriteEntry(字符串消息,EventLogEntryType类型)在C:\Program Files(x86)\CSI\WeblogicConsumerService\WeblogicSconsumer.cs:line 139位于C:\Program Files(x86)\CSI\WeblogicConsumerService\WeblogicSconsumer.cs:line 70在System.ServiceProcess.ServiceBase.DeferredStop()

这里是OnStop()方法

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

这些事件日志开始让我很困惑。我在其他服务中也使用过同样的方法登录,从未遇到过这样的问题。我怎么能在这个服务中得到这些错误,但它与我所做的所有其他服务没有太大区别:(

我认为这是您的问题:

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值会引发异常但是,单个事件日志可以与多个源相关联

我的建议是:

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

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

最新更新