Чи є спосіб записати в цей журнал подій:
Або принаймні якийсь інший журнал Windows за замовчуванням, де мені не потрібно реєструвати джерело подій ?
ServiceBase.EventLog
. За замовчуванням ім'я Джерела - ім'я служби.
Чи є спосіб записати в цей журнал подій:
Або принаймні якийсь інший журнал Windows за замовчуванням, де мені не потрібно реєструвати джерело подій ?
ServiceBase.EventLog
. За замовчуванням ім'я Джерела - ім'я служби.
Відповіді:
Так, є спосіб записати в журнал подій, який ви шукаєте. Вам не потрібно створювати нове джерело, просто скористайтеся наявним джерелом, яке часто має те саме ім'я, як ім'я EventLog, а також у деяких випадках, як Приклад журналу подій, можна отримати без адміністративних привілеїв *.
* Інші випадки, коли ви не можете отримати доступ до нього безпосередньо, це, наприклад, Security EventLog, до якого доступ має лише операційна система.
Я використовував цей код, щоб записати безпосередньо в журнал подій Застосування:
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = "Application";
eventLog.WriteEntry("Log message example", EventLogEntryType.Information, 101, 1);
}
Як бачимо, джерело EventLog - те саме, що і ім'я EventLog. Причину цього можна знайти в Центрі подій @ Windows Dev Center (я виділив жирною частиною, що стосується імені джерела):
Кожен журнал у ключі Eventlog містить підрозділи, що називаються джерелами подій. Джерело події - це назва програмного забезпечення, яке реєструє подію. Часто це ім'я програми або назва підкомпонента програми, якщо програма велика. Ви можете додати до реєстру максимум 16 384 джерел подій.
Ви можете використовувати клас EventLog, як пояснено в розділі Як: Записати в журнал подій програми (Visual C #) :
var appLog = new EventLog("Application");
appLog.Source = "MySource";
appLog.WriteEntry("Test log message");
Однак вам потрібно буде налаштувати це джерело "MySource" за допомогою адміністративних привілеїв:
Використовуйте WriteEvent і WriteEntry для запису подій до журналу подій. Ви повинні вказати джерело події для запису подій; ви повинні створити та налаштувати джерело події перед тим, як написати перший запис із джерелом.
Як зазначено в MSDN (наприклад, https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog(v=vs.110).aspx ), для перевірки неіснуючого джерела та створення джерела потрібен адміністратор привілей.
Однак можна використовувати джерело "Application" без. Проте в моєму тесті під Windows 2012 Server r2 я отримую такий запис журналу, використовуючи джерело "Application":
Опис для ідентифікатора події xxxx з вихідного додатка неможливо знайти. Або компонент, який викликає цю подію, не встановлений на вашому локальному комп'ютері, або установка пошкоджена. Ви можете встановити або відремонтувати компонент на локальному комп'ютері. Якщо подія виникла на іншому комп'ютері, інформацію про дисплей потрібно було зберегти разом із подією. До події була включена така інформація: {my message entry message} ресурс повідомлення присутній, але повідомлення не знайдено в таблиці рядків / повідомлень
Я визначив наступний метод для створення джерела:
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 замість цього спробувати / catch, але не впевнений, що ми можемо уникнути улову.
Можна також створити джерело зовні, наприклад, у підвищеній потужності:
New-EventLog -LogName Application -Source MyApp
Тоді, використовуючи "MyApp" у наведеному вище способі, НЕ створюватиме винятки, і EventLog можна створити з цим джерелом.
Це клас реєстратора, який я використовую. Метод приватного Log () маєEventLog.WriteEntry()
ньому є , який ви фактично записуєте до журналу подій. Я включаю тут весь цей код, тому що це зручно. Окрім ведення журналу, цей клас також переконається, що повідомлення не буде занадто довгим для запису в журнал подій (він уріже повідомлення). Якщо повідомлення було занадто довгим, ви отримаєте виняток. Абонент може також вказати джерело. Якщо абонент цього не робить, цей клас отримає джерело. Сподіваюся, це допомагає.
До речі, ви можете отримати 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;
}
}
}
спробуйте
System.Diagnostics.EventLog appLog = new System.Diagnostics.EventLog();
appLog.Source = "This Application's Name";
appLog.WriteEntry("An entry to the Application event log.");