c#.NET中日志信息写入Windows日志中解决方案_C#教程

1、 目的  
应用系统的开发和维护离不开日志系统,选择一个功能强大的日志系统解决方案是应用系统开发过程中很重要的一部分。在.net环境下的日志系统解决方案有许多种,log4net是其中的佼佼者。 
在Windows2000及以上操作系统中,有一个Windows日志系统,它包括应用程序(Application)事件日志、系统(System)日志和安全(Security)日志,事件日志也可以是自定义日志。在.net Framework中也提供了相应的类和接口来使用应用程序事件日志或者自定义事件日志。使用Windows日志可以使应用系统与操作系统更好的结合,与单纯使用自定义的日志系统相比,因为有了操作系统的支持,查询和管理日志更方便。在实际应用中,根据实际情况,可以选择一种合适的日志解决方案,也可以自定义日志系统和Windows日志系统两种日志解决方案同时使用。 
2、 使用Windows日志的方法  
2.1、方法概述  
在.net Framework中提供了一个类EventLog,使用EventLog类可以添加新的事件日志条目或从服务器事件日志中获取已有的条目。EventLog类包括一个WriteEntry()方法,可以用它来把一个新的事件写入到事件日志中。在写入一个新的条目到事件日志时,是使用特定的事件源(event source)来把条目写入到特定的事件日志中。 
事件源对于事件日志而言是唯一的。在Windows2000及以上操作系统中,包括一个事件日志:应用程序(Application)事件日志,还有系统(System)日志和安全(Security)日志,并且系统允许自定义事件日志。使用EventLog类,可以将日志条目添加到应用程序(Application)事件日志中,也可以添加到自定义事件日志中。事件源相当于事件日志的下一级目录,每一条日志条目都必须对应一个事件源。EventLog类可以创建一个自定义事件日志,也可以创建一个事件源,事件源可以创建在应用程序(Application)事件日志中,也可以创建在自定义事件日志中。Windows日志系统如下图所示:
为了便于不同应用系统之间的日志区分和查看方便,一般将事件源创建在自定义事件日志中,可以创建多个事件日志,一个事件日志也可以创建多个事件源。
2.2、事件日志和事件源创建方法 
创建一个新的事件日志或事件源时,其实是在对注册表添加一个条目。由于写注册表要求特殊的权限,所以在Web项目中创建事件日志和事件源就存在权限和安全的问题,Application项目中不存在此问题,本文重点讲述Web项目中Windows日志使用方法,Application项目中的使用方法类似于Web项目,抛弃掉Web项目中的权限和安全处理即可,本文不再赘述。
在Web项目中,当使用asp.net向系统中创建一个事件日志或者一个事件源时,可能会得到如下异常错误消息: System.Security.SecurityException: 不允许所请求的注册表访问权。这是因为运行asp.net进程的默认帐户是ASPNET(在IIS6.0下面是NetworkService),而此账户默认只有读权限,没有写权限,所以不能创建事件日志或事件源。解决此问题的办法有提升ASPNET帐户的权限、不在程序内部创建事件日志或事件源等,主要有以下三种解决方案:
A、  在程序运行之前,定义要使用的事件日志和事件源,打开注册表编辑器,手工将事件日志和事件源添加到注册表中。主要步骤如下:
①     点击“开始”菜单,再点击“运行”。
②     在“运行”的“打开”框中输入“regedit”,然后按OK按钮,打开注册表编辑器。
③     在注册表编辑器中找到下列子键:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog
④     右键单击“Eventlog”,点击“新建”,再点“项”,将在“Eventlog”的下一级创建一个新的项目,将此项目命名为“TDDN”, TDDN项就是事件日志,可以根据实际情况为此项命名,比如可以命名为项目名称。
⑤     在“TDDN”项上单击右键,点击“新建”,再点“项”,将在“TDDN”的下一级创建一个新的项,将此项命名为“Weblog”, Weblog项就是事件源,此项也可以根据实际情况命名。
⑥     关闭注册表编辑器。
这样事件日志和事件源就建好了,如果需要多个事件日志或事件源,重复以上过程。这种方法要求对注册表比较熟悉,操作起来可能有一点复杂,可以写一个类来实现配置注册表,只要运行该类便可添加相应的项目,免除了手工添加的繁琐,这是第二种解决方案,方法如下:
B、  在System.Diagnostics命名空间中有一个EventLogInstaller类,它能够创建和配置应用程序在运行时要读写的事件日志和事件源。通过下列步骤,便能够使用EventLogInstaller类来创建一个事件日志和事件源:
①     用C#来创建一个名为EventLogSourceInstaller的“类库”。
②     在此项目中添加对System.Configuration.Install.dll的引用。
③     将自动产生的Class1.cs更名为MyEventLogInstaller.cs。
④     在MyEventLogInstaller.cs中的写入以下代码:
using System;
using System.Diagnostics;
using System.ComponentModel;
using System.Configuration.Install;
namespace EventLogSourceInstaller {
[RunInstaller(true)]
public class MyEventLogInstaller: Installer{
public  EventLogInstaller myEventLogInstaller;
public MyEventLogInstaller(){
//Create Instance of EventLogInstaller
myEventLogInstaller = new EventLogInstaller();
// Set the Source of Event Log, to be created.
myEventLogInstaller.Source = "WebLog";
// Set the Log that source is created in
myEventLogInstaller.Log = "TDDN";
Installers.Add(myEventLogInstaller);
}
}
}
⑤     生成此项目,得到EventLogSourceInstaller.dll。
⑥     打开Visual Studio .NET 命令提示,转到EventLogSourceInstaller.dll所在目录。
⑦     运行此命令来创建事件日志和事件源,运行方法为:输入命令InstallUtil EventLogSourceInstaller.dll。
这样程序就在系统中创建一个事件日志:TDDN,在事件日志TDDN下创建了一个事件源:WebLog。
以上的这两种解决方案都是在应用系统运行之前,为系统手工添加事件日志和事件源,这样做没有安全权限问题,不存在安全隐患。更方便的方法还可以在应用系统运行时,让程序自动创建事件日志和事件源,这种方法必须提升ASPNET帐户的系统操作权限,或者给asp.net进程一个有更大权限的模拟帐号。模拟帐号的实现比较复杂,而且功能和安全性上和提升ASPNET帐户没有区别,这里采用的方法是提升ASPNET帐户的权限。以下是第三种解决方案:
C、  提升ASPNET帐户的权限可以直接在Windows系统管理中给ASPNET帐户添加对系统的读写权限,但是这样做存在很严重的安全问题,asp.net进程有直接读写操作系统的权限,将给系统带来很大的安全隐患。这里采用的提升ASPNET帐户权限的方法是只将系统日志的操作权限赋给ASPNET帐户,这样虽然还存在一定的安全隐患,但是隐患已经大大降低,并且可以在程序内部自由创建事件日志和事件源,极大的提高了灵活性。ASPNET帐户权限提升方法如下:
①     点击“开始”,“运行”,输入“regedit”,打开注册表编辑器。
②     在注册表编辑器中找到下列子键:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog
③     在Eventlog项目上单击右键,在弹出的菜单中选择“访问许可”选项,然后找到本机的ASPNET帐户加进来,并赋予读写权限。
这样,ASPNET帐户就有了读写系统日志的权限,就可以在程序中根据情况自由创建事件日志和事件源了。在程序中创建事件日志和事件源的方法如下:
调用 EventLog类的CreateEventSource 方法并指定数据源字符串和要创建的事件日志名称,如果将事件日志名称指定为空 (""),事件日志名称将默认为Application,这样不会创建新事件日志,但会为应用程序(Application)事件日志创建指定的数据源。如果创建一个新的事件日志,则在确定事件日志名称是否唯一时将只计算指定字符串的前8 个字母。如下代码所示:
System.Diagnostics.EventLog.CreateEventSource("WebLog", "TDDN");
将创建一个事件日志为TDDN,在该事件日志下创建一个事件源WebLog。要在远程计算机上创建自定义事件日志,要将此计算机名指定为第三个参数。以下代码提供了一个示例:
System.Diagnostics.EventLog.CreateEventSource(" WebLog ", " TDDN ", "myserver");
将在远程计算机myserver上创建该事件日志和事件源。
2.3、写入Windows日志的方法 
事件日志与事件源创建的问题解决了,接下来就可以在程序中将日志信息写入到Windows系统日志中了。写入方法是,首先创建EventLog类的一个实例,将其Source属性与事件源名称相关联,最后调用WriteEntry方法来往事件日志中添加日志信息。下面是一段写入系统日志的简单示例代码:
EventLog eventLog = null;
if (!(EventLog.SourceExists("WebLog"))){            
EventLog.CreateEventSource("WebLog", "TDDN");
}
if (eventLog == null){
eventLog = new EventLog("TDDN");
eventLog.Source = "WebLog";

eventLog.WriteEntry("This is error!", EventLogEntryType.Error);
}
上面程序段中首先判断数据源“WebLog”是否存在,如果不存在调用CreateEventSource方法创建该事件源,然后将事件源与EventLog 类的Source属性关联,进行写操作。传递给WriteEntry方法的第一个参数代表要记录的日志消息,可以写入任何消息。第二个参数代表事件日志的类型。
A、 事件日志类型分类
事件日志的类型用于指示事件日志的严重度。每个事件必须具有单一的类型,应用程序在报告事件时将指示该类型。事件查看器使用该类型来确定在日志的列表视图中显示哪一个图标。它分为如下五类:
①     Error:错误事件,它指示用户应该知道的严重问题(通常是功能或数据的丢失)。
②     FailureAudit:失败审核事件,它指示当审核访问尝试失败(例如打开文件的尝试失败)时发生的安全事件。
③     Information:信息事件,它指示重要、成功的操作。
④     SuccessAudit:成功审核事件,它指示当审核访问尝试成功(例如成功登录)时发生的安全事件。
⑤     Warning:警告事件,它指示并不立即具有重要性的问题,但此问题可能表示将来会导致问题的条件。
在实际应用中,选择合适的事件日志类型,可以使日志记录更清晰明了,帮助开发维护人员对应用系统更好的监控和维护。
B、 针对事件日志的五种类型分类,可以在应用程序中写一个通用的类,为每一个类型写一个方法来写入事件日志。
下面是自定义的通用类的代码片断:
public void Error(string sourceName, string message){
EventLog eventLog = null;
if (!(EventLog.SourceExists(sourceName))){
EventLog.CreateEventSource(sourceName, "TDDN");
}
if (eventLog == null){
eventLog = new EventLog("TDDN");
eventLog.Source = sourceName;
}
eventLog.WriteEntry(message, EventLogEntryType.Error);
}
public void Warning(string sourceName, string message){
EventLog eventLog = null;
if (!(EventLog.SourceExists(sourceName))){
EventLog.CreateEventSource(sourceName, "TDDN");
}
if (eventLog == null){
eventLog = new EventLog("TDDN");
eventLog.Source = sourceName;
}
eventLog.WriteEntry(message,System.Diagnostics.EventLogEntryType.Warning);
}
类似的可以写出其它三种类型的事件日志写入方法。该类方法将事件源(sourceName)和日志消息(message)作为参数传递,这样可以提高事件日志写入的灵活性。
C、 调用通用类事件日志写入的方法
通用类方法的调用非常简单,如下代码片断是调用通用类中Error方法的一个范例:
string strSourceName="WebLog";
CoustomEventLog log=new CoustomEventLog();
log.Error(strSourceName,"This is Error!");
strSourceName是事件源,log是CoustomEventLog类(即通用类)的一个实例,然后调用Error方法将日志消息“This is Error!”写入到事件日志中。
也可以将程序中抛出的异常信息写入事件日志:
string strSourceName="WebLog";
CoustomEventLog log=new CoustomEventLog();
try{
//执行事件

时间: 2016-03-09

c#.NET中日志信息写入Windows日志中解决方案_C#教程的相关文章

如何让textbox中的信息更新到数据库中的列中

问题描述 如何让textbox中的信息更新到数据库中的列中 如何让textbox1和textbox2中的信息更新到数据库中的列中 解决方案 让textbox1和textbox2中的信息更新到数据库中,可以分为两步: (1) 从 textbox 中获取输入的数据,这个我想应该没有什么问题吧: (2)将数据写入数据库指定的列中,这个要看具体用的是什么数据库?个人如果对数据库不熟悉,就找点入门的资料看看. 解决方案二: using (SqlConnection connection = new Sql

memo-C++builder中怎么样将Memo中的文本写入到word中

问题描述 C++builder中怎么样将Memo中的文本写入到word中 C++builder中怎么样将Memo中的文本写入到word中 解决方案 void __fastcall TForm1::Button1Click(TObject *Sender) { Variant vWordApp; try { vWordApp = Variant::CreateObject("Word.Application"); } catch(...) { MessageBox(0, L"启

模拟使用Flume监听日志变化,并且把增量的日志文件写入到hdfs中

1.采集日志文件时一个很常见的现象 采集需求:比如业务系统使用log4j生成日志,日志内容不断增加,需要把追加到日志文件中的数据实时采集到hdfs中. 1.1.根据需求,首先定义一下3大要素: 采集源,即source-监控日志文件内容更新:exec 'tail -F file' 下沉目标,即sink-HDFS文件系统:hdfs sink Source和sink之间的传递通道--channel,可用file channel也可以用 内存channel. 1.2.进入/home/tuzq/softw

C/C++程序开发中实现信息隐藏的三种类型_C 语言

无论是模块化设计,还是面向对象设计,还是分层设计,实现子系统内部信息的对外隐藏都是最关键的内在要求.以本人浅显的经验,把信息隐藏按照程度的不同分成(1)不可见不可用(2)可见不可用(3)可见可用. 1 不可见不可用 就是说模块内部的变量.结构体.类定义对外部而已完全隐藏,外部对此一无所知.常用的实现方法就是利用不透明指针,请参见我的博文C语言开发函数库时利用不透明指针对外隐藏结构体细节. 这种方法同样适用于C++语言,一种可能的实现方式为面向接口编程. 头文件 IMyClass.h class

OpenCV - 将图片的二进制信息写入到文件中

遇到的错误, 应该是配置问题, 请自行百度配置方式 // imageToDat.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" //图像写入二进制(.dat)文件 #include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp> #include <opencv2/ml/ml.hpp> #include <opencv2/highgui/high

在Winform和WPF中注册全局快捷键实现思路及代码_C#教程

快捷键辅助类 复制代码 代码如下: class HotKey { /// <summary> /// 如果函数执行成功,返回值不为0. /// 如果函数执行失败,返回值为0.要得到扩展错误信息,调用GetLastError..NET方法:Marshal.GetLastWin32Error() /// </summary> /// <param name="hWnd">要定义热键的窗口的句柄</param> /// <param na

C#中控制远程计算机的服务的方法_C#教程

在.net中提供了一些类来显示和控制Windows系统上的服务,并可以实现对远程计算机服务服务的访问,如System.ServiceProcess命名空间下面的ServiceController 类,System.Management下面的一些WMI操作的类.虽然用ServiceController可以很方便的实现对服务的控制,而且很直观.简洁和容易理解.但是我认为他的功能同通过WMI来操作服务相比,那可能就有些单一了,并且对多个服务的操作可能就比较麻烦,也无法列出系统中的所有服务的具体数据.这

C#设置子窗体在主窗体中居中显示解决方案_C#教程

问题的开始是由C#传传看主群里的印醒提出来的,下面我来说一下解决方案吧 其实表面上看是很简单的 开始吧,现在有两个窗体Form1主窗体,Form2子窗体 而且我相信大部分人都会这样写 在子窗体的Load事件中 这样写 复制代码 代码如下: this.StartPosition = FormStartPosition.CenterParent; 其实这样写是不对的,正确的写法应该是 复制代码 代码如下: this.StartPosition = FormStartPosition.CenterSc

C#在winform中实现数据增删改查等功能_C#教程

winform中利用ado.net实现对单表的增删改查的详细例子,具体如下: 1.前言: 运行环境:VS2013+SQL2008+Windows10 程序界面预览: 使用的主要控件:dataGridview和menuStrip等.  2.功能具体介绍: 1.首先,我们要先实现基本的数据操作,增删改查这几个操作. (1)先定义一个数据库操作的公共类: using System; using System.Collections.Generic; using System.Linq; using S