写入Windows应用程序事件日志,无需注册事件源

有没有办法写这个事件日志:

在这里输入图像说明

或者至less,一些其他的Windows默认日志, 我不需要注册一个事件源

是的,有一种方法可以写入您正在查找的事件日志。 您不需要创build新的源代码,只需简单地使用现有名称(通常与EventLog名称相同),并且在某些情况下(如事件日志应用程序)可以在没有pipe理权限*的情况下访问。

*其他情况下,无法直接访问的情况,例如安全事件日志,只能由操作系统访问。

我用这个代码直接写入事件日志应用程序:

 using (EventLog eventLog = new EventLog("Application")) { eventLog.Source = "Application"; eventLog.WriteEntry("Log message example", EventLogEntryType.Information, 101, 1); } 

如您所见,EventLog源与EventLog的名称相同。 这个原因可以在Event Sources @ Windows开发中心find (我加粗了引用源名称的部分):

Eventlog密钥中的每个日志都包含称为事件源的子密钥。 事件源是logging事件的软件的名称。 如果应用程序很大, 通常是应用程序的名称或应用程序的子组件的名称。 您最多可以将16,384个事件源添加到registry中。

这是我使用的logging器类。 私有的Log()方法中有EventLog.WriteEntry() ,这就是你实际写入事件日志的方式。 我在这里包含所有这些代码,因为它很方便。 除了日志logging之外,这个类还将确保消息不会太长以写入事件日志(它会截断消息)。 如果消息太长,你会得到一个例外。 调用者也可以指定源。 如果调用者不这样做,这个类将获得源代码。 希望能帮助到你。

顺便说一句,你可以从网上获得一个ObjectDumper。 我不想在这里发表一切。 我从这里得到了: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Samples\1033\CSharpSamples.zip\LinqSamples\ObjectDumper

 using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; using Xanico.Core.Utilities; namespace Xanico.Core { /// <summary> /// Logging operations /// </summary> public static class Logger { // Note: The actual limit is higher than this, but different Microsoft operating systems actually have // different limits. So just use 30,000 to be safe. private const int MaxEventLogEntryLength = 30000; /// <summary> /// Gets or sets the source/caller. When logging, this logger class will attempt to get the /// name of the executing/entry assembly and use that as the source when writing to a log. /// In some cases, this class can't get the name of the executing assembly. This only seems /// to happen though when the caller is in a separate domain created by its caller. So, /// unless you're in that situation, there is no reason to set this. However, if there is /// any reason that the source isn't being correctly logged, just set it here when your /// process starts. /// </summary> public static string Source { get; set; } /// <summary> /// Logs the message, but only if debug logging is true. /// </summary> /// <param name="message">The message.</param> /// <param name="debugLoggingEnabled">if set to <c>true</c> [debug logging enabled].</param> /// <param name="source">The name of the app/process calling the logging method. If not provided, /// an attempt will be made to get the name of the calling process.</param> public static void LogDebug(string message, bool debugLoggingEnabled, string source = "") { if (debugLoggingEnabled == false) { return; } Log(message, EventLogEntryType.Information, source); } /// <summary> /// Logs the information. /// </summary> /// <param name="message">The message.</param> /// <param name="source">The name of the app/process calling the logging method. If not provided, /// an attempt will be made to get the name of the calling process.</param> public static void LogInformation(string message, string source = "") { Log(message, EventLogEntryType.Information, source); } /// <summary> /// Logs the warning. /// </summary> /// <param name="message">The message.</param> /// <param name="source">The name of the app/process calling the logging method. If not provided, /// an attempt will be made to get the name of the calling process.</param> public static void LogWarning(string message, string source = "") { Log(message, EventLogEntryType.Warning, source); } /// <summary> /// Logs the exception. /// </summary> /// <param name="ex">The ex.</param> /// <param name="source">The name of the app/process calling the logging method. If not provided, /// an attempt will be made to get the name of the calling process.</param> public static void LogException(Exception ex, string source = "") { if (ex == null) { throw new ArgumentNullException("ex"); } if (Environment.UserInteractive) { Console.WriteLine(ex.ToString()); } Log(ex.ToString(), EventLogEntryType.Error, source); } /// <summary> /// Recursively gets the properties and values of an object and dumps that to the log. /// </summary> /// <param name="theObject">The object to log</param> [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Xanico.Core.Logger.Log(System.String,System.Diagnostics.EventLogEntryType,System.String)")] [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "object")] public static void LogObjectDump(object theObject, string objectName, string source = "") { const int objectDepth = 5; string objectDump = ObjectDumper.GetObjectDump(theObject, objectDepth); string prefix = string.Format(CultureInfo.CurrentCulture, "{0} object dump:{1}", objectName, Environment.NewLine); Log(prefix + objectDump, EventLogEntryType.Warning, source); } private static void Log(string message, EventLogEntryType entryType, string source) { // Note: I got an error that the security log was inaccessible. To get around it, I ran the app as administrator // just once, then I could run it from within VS. if (string.IsNullOrWhiteSpace(source)) { source = GetSource(); } string possiblyTruncatedMessage = EnsureLogMessageLimit(message); EventLog.WriteEntry(source, possiblyTruncatedMessage, entryType); // If we're running a console app, also write the message to the console window. if (Environment.UserInteractive) { Console.WriteLine(message); } } private static string GetSource() { // If the caller has explicitly set a source value, just use it. if (!string.IsNullOrWhiteSpace(Source)) { return Source; } try { var assembly = Assembly.GetEntryAssembly(); // GetEntryAssembly() can return null when called in the context of a unit test project. // That can also happen when called from an app hosted in IIS, or even a windows service. if (assembly == null) { assembly = Assembly.GetExecutingAssembly(); } if (assembly == null) { // From http://stackoverflow.com/a/14165787/279516: assembly = new StackTrace().GetFrames().Last().GetMethod().Module.Assembly; } if (assembly == null) { return "Unknown"; } return assembly.GetName().Name; } catch { return "Unknown"; } } // Ensures that the log message entry text length does not exceed the event log viewer maximum length of 32766 characters. private static string EnsureLogMessageLimit(string logMessage) { if (logMessage.Length > MaxEventLogEntryLength) { string truncateWarningText = string.Format(CultureInfo.CurrentCulture, "... | Log Message Truncated [ Limit: {0} ]", MaxEventLogEntryLength); // Set the message to the max minus enough room to add the truncate warning. logMessage = logMessage.Substring(0, MaxEventLogEntryLength - truncateWarningText.Length); logMessage = string.Format(CultureInfo.CurrentCulture, "{0}{1}", logMessage, truncateWarningText); } return logMessage; } } } 

您可以使用EventLog类,如“ 如何:写入应用程序事件日志(Visual C#)”中所述 :

 var appLog = new EventLog("Application"); appLog.Source = "MySource"; appLog.WriteEntry("Test log message"); 

但是,您需要使用pipe理权限configuration此 “MySource”:

使用WriteEvent和WriteEntry将事件写入事件日志。 你必须指定一个事件源来写事件; 您必须先创build并configuration事件源,然后才能使用源代码编写第一个条目。

正如在MSDN(例如https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog(v=vs.110).aspx )中所述,检查一个不存在的源并创build一个源需要pipe理员特权。

然而,没有可能使用源“应用程序” 。 在Windows 2012 Server r2下的testing中,我使用“应用程序”来源获得以下日志条目:

无法find来自源应用程序的事件ID xxxx的说明。 引发此事件的组件未在本地计算机上安装,或者安装已损坏。 您可以在本地计算机上安装或修复组件。 如果事件发生在另一台计算机上,显示信息必须与事件一起保存。 事件中包含以下信息:{my event entry message}消息资源存在,但在string/消息表中找不到消息

我定义了以下方法来创build源代码:

  private string CreateEventSource(string currentAppName) { string eventSource = currentAppName; bool sourceExists; try { // searching the source throws a security exception ONLY if not exists! sourceExists = EventLog.SourceExists(eventSource); if (!sourceExists) { // no exception until yet means the user as admin privilege EventLog.CreateEventSource(eventSource, "Application"); } } catch (SecurityException) { eventSource = "Application"; } return eventSource; } 

我打电话给currentAppName = AppDomain.CurrentDomain.FriendlyName

也许可以使用EventLogPermission类来代替try / catch,但不确定我们可以避免这种情况。

也可以从外部创build源代码,例如在高架Powershell中:

 New-EventLog -LogName Application -Source MyApp 

然后,在上面的方法中使用“MyApp”将不会生成exception,并且可以使用该源创buildEventLog。

尝试

  System.Diagnostics.EventLog appLog = new System.Diagnostics.EventLog(); appLog.Source = "This Application's Name"; appLog.WriteEntry("An entry to the Application event log.");