如何在不使用第三方库的情况下,在C#中进行日志记录?

92

我希望在我的应用程序中实现日志记录,但不想使用类似log4net的外部框架。

因此,我想做一些类似DOS的echo输出到文件。最有效的方法是什么?

是否有一种方法可以在不使用外部框架的情况下记录未处理的异常?


1
你可以使用内置的System.Diagnostics.TraceSource。<br> 以下是内置的跟踪侦听器列表the built in trace listeners + FileLogTraceListener。网络上有很多手册比如这份,还有Jeff Atwood写的这篇文章 - HuBeZa
2
我觉得企业库比log4net更好的选择。 - hungryMind
如果您仅寻求简单的控制台日志记录,则System.Diagnostics.Tracing可能适合您。Trace可像Console一样使用(Trace.WriteLine)。 - Paul
7个回答

66
public void Logger(string lines)
{
  //Write the string to a file.append mode is enabled so that the log
  //lines get appended to  test.txt than wiping content and writing the log

  using(System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\test.txt", true))
  {
    file.WriteLine(lines);
  }
}

更多信息请参见MSDN


22
你应该在文件上使用 using,尽管它是方法本地的,但会很快被释放。 - markmnl
19
请注意,当file.WriteLine(lines);抛出异常时,代码将永远不会运行file.Close();。使用using语句块相当于try { // using block } finally { // Dispose }语句块。这意味着即使在using语句块内部的代码抛出异常,对象也会被处理并释放。 - Memet Olsen
7
如果在日志记录完成之前再次调用此方法会发生什么?您将会收到一个错误提示 - 进程无法访问文件'C:\test.txt',因为它正在被另一个进程使用。是否有人知道如何解决这个问题? - Mike Sportsman

23

我宁愿不使用类似log4j.net这样的外部框架。

为什么呢?Log4net可能已经满足了您的大部分需求,例如请查看此类:RollingFileAppender

Log4net有很好的文档,并且在网络上有成千上万的资源和用例。


4
只需在您的项目中添加引用并放置一些XML配置-非常容易。搜索log4net教程,选择最适合您的教程。 - empi
23
使用Nuget。使用外部库将变得轻而易举。 - heneryville
3
在家庭项目中使用外部框架很好,但对于大型企业而言,开放源代码项目可能会带来潜在威胁,因为公司外的人可以在项目中注入代码。因此,通常有严格的监管。 - Kobor42
37
为什么有这么多赞?问题两次明确表示OP不想使用外部框架,并明确提到不想使用Log4net。这应该是一个评论,而不是一个回答。 - RyanfaeScotland
9
你说得对,也许这不适合题主,但请不要忘记这是一个公开的网站。由于问题标题只说明了“如何在c#中记录日志”,所以像我这样可以使用任何库的人也会来到这里并发现这个答案很有用。事实上,当我谷歌搜索“c# logging”时,这个帖子就是第一个结果。 - swenzel
显示剩余8条评论

18
你可以直接写入事件日志。请参考以下链接:
http://support.microsoft.com/kb/307024
http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog.aspx

下面是 MSDN 提供的示例:

using System;
using System.Diagnostics;
using System.Threading;

class MySample{

    public static void Main(){

        // 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;
        }

        // Create an EventLog instance and assign its source.
        EventLog myLog = new EventLog();
        myLog.Source = "MySource";

        // Write an informational entry to the event log.    
        myLog.WriteEntry("Writing to event log.");

    }
}

1
在不同的类中使用相同的EventLog,最佳实践是什么?将其作为参数传递给构造函数?从某个单例类静态访问它?还是有更好的方法? - dpelisek

15

如果您正在寻找一种真正简单的记录方式,您可以使用这个一行命令。如果文件不存在,则会创建该文件。

System.IO.File.AppendAllText(@"c:\log.txt", "mymsg\n");

这个解决方案的问题在于它增加了IO操作。因此,在批量算法操作中不建议使用它进行日志记录。 - Rami Yampolsky
如果您编写了一些需要大量CPU操作的代码,并且在代码运行期间记录日志,那么记录日志的过程将占用一些时间,这些时间本应用于实际的算法实现。因此,您最好尽可能地减少这种“浪费”时间。像上面的示例中进行的IO操作非常耗时,因此如果您的代码中有很多记录日志的命令,整个执行速度可能会变慢1000倍! - Rami Yampolsky
@RamiYampolsky,我又测试了一遍,用了10秒钟。我会在下一个评论中发布代码。这是我的操作步骤:(1)手动删除日志文件,(2)在“C#语句”模式下运行LINQPad 4中的代码,(3)记录时间(10.101秒),(4)查看日志文件:最后一行是“mymsg,99999,704982704”,它在我的文本编辑器中的第100,000行,(5)再次运行代码,将其附加到同一文件中,(6)花费了10.845秒,(7)验证文件。 - dan-gph
int sum = 0; for (int i = 0; i < 100000; ++i) { sum += i; System.IO.File.AppendAllText(@"e:\scratch\log.txt", string.Format("mymsg,{0},{1}\n", i, sum)); } 整型变量sum初始化为0; 循环执行100000次,每次将i的值加到sum中; 使用System.IO.File.AppendAllText方法将格式化后的字符串写入指定路径下的log.txt文件。 - dan-gph
让我们在聊天中继续这个讨论 - dan-gph
显示剩余4条评论

7

在我发现ELMAH之前,我曾经自己编写错误日志记录。但是我从未像ELMAH那样完美地解决邮件发送问题。


我会看一下,关于我的推理,请查看我的Empi评论。 - IAdapter
ELMAH非常直接,甚至不好笑,你只需要将它放入并在Web配置中添加几行代码,它就可以工作了。 - jonezy
就你需要了解应用程序何时即将/开始崩溃这一要求而言,我发现elmah比大多数其他工具更好,因为它能够发送电子邮件,只要服务器正常运行,你就可以从elmah收到错误电子邮件。 - jonezy

6
如果您想保持与.NET的紧密联系,请查看Enterprise Library Logging应用程序块。请点击这里。或者,如果您需要快速入门教程,请查看这里。我已经使用过Enterprise Library中的验证应用程序块,它确实符合我的需求,并且非常容易在您的项目中“继承”(安装并引用它!)。

4

如果你想要自定义错误日志,你可以轻松地编写自己的代码。我将给您展示我的某个项目中的一小段代码。

public void SaveLogFile(object method, Exception exception)
{
    string location = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\FolderName\";
    try
    {
        //Opens a new file stream which allows asynchronous reading and writing
        using (StreamWriter sw = new StreamWriter(new FileStream(location + @"log.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite)))
        {
            //Writes the method name with the exception and writes the exception underneath
            sw.WriteLine(String.Format("{0} ({1}) - Method: {2}", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString(), method.ToString()));
            sw.WriteLine(exception.ToString()); sw.WriteLine("");
        }
    }
    catch (IOException)
    {
        if (!File.Exists(location + @"log.txt"))
        {
            File.Create(location + @"log.txt");
        }
    }
}

然后实际上写入错误日志只需编写(q是捕获的异常)
SaveLogFile(MethodBase.GetCurrentMethod(), `q`);

7
你知道当文件还不存在时,你会错过第一个入口吗? - oɔɯǝɹ

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