首页 > 解决方案 > 在 .NET 服务中设置和使用自定义事件日志的正确方法?

问题描述

我已经找到了几个关于此的主题,但不知何故,他们都设法避免了真正的问题解决方案/假设是显而易见的。
(例如这里这里这里这里这里

我在安装期间检查并创建新的事件日志+源,并指定它们在操作期间使用,但仍然以某种方式“EventSourceName”事件最终出现在应用程序日志中。

这是为什么?


以下是我的代码片段:

安装人员:

namespace Service_Name
{
    [RunInstaller(true)]
    public partial class ProjectInstaller : System.Configuration.Install.Installer
    {
        public ProjectInstaller()
        {
            if (!System.Diagnostics.EventLog.SourceExists("EventSourceName"))
            {
                System.Diagnostics.EventLog.CreateEventSource(
                    "EventSourceName", "EventLogName");
            }
            InitializeComponent();
        }

        private void serviceProcessInstaller1_AfterInstall(object sender, InstallEventArgs e)
        {

        }
    }
}

服务:

public Service_Name()
{
    InitializeComponent();
}

protected override void OnStart(string[] args)
{
    ServiceEventLog = new EventLog();
    ServiceEventLog.Source = "EventSourceName"; // This is different from Service Name
    ServiceEventLog.Log = "EventLogName"; // This is different from Service Name
    ..
    ServiceEventLog.WriteEntry("Service Init");
    Worker = new Thread(CodeWorker);
    Worker.Start();
}

private void CodeWorker()
{
    //.. operational code
    while (true)
    {
        try
        {
            //.. operational code
            ServiceEventLog.WriteEntry("<operational event data here>", (EventLogEntryType)4, 0);
        }
        catch (Exception Error)
        {
            ServiceEventLog.WriteEntry(string.Format("<error event data here>", (EventLogEntryType)1, 0);
            throw;
        }
        //.. operational code
    }
}

事实证明,代码按原样完美运行,但是在使用事件日志时要记住重要的事情;

EventLog.CreateEventSource 方法有一个重要的脚注:

如果源已映射到日志并且您将其重新映射到新日志,则必须重新启动计算机才能使更改生效。

我之前已将源映射到另一个与服务本身命名相同的事件日志。使用与服务本身相同的名称会导致多个其他问题,我最终通过使用另一个日志名称来解决该问题,但在对新代码版本进行测试之前没有重新启动测试系统。

但正如 Caius Jard 在下面指出的,部分代码是多余的:
ServiceEventLog.Log = "EventLogName"不需要指定,因为 Source 已经注册到 Log。

标签: c#.net

解决方案


文档指出“如果在设置 Source 属性后更改 Log 属性,则写入日志条目会引发异常。”。

MSDN上的示例代码只是设置了Source属性然后调用WriteEvent,并没有在设置Source之前或之后设置Log

我建议您删除设置 Log 属性的调用;我怀疑您对 WriteEvent 的调用正在崩溃,并且正在尝试捕获 catch 中的调用也崩溃了。如果是“写入日志”失败,则“尝试写入此日志,如果失败,请尝试写入此日志”可能不是理想的代码结构


推荐阅读