C'è un modo per scrivere nel registro eventi:
O almeno, qualche altro registro predefinito di Windows, dove non devo registrare una fonte di eventi ?
ServiceBase.EventLog
. Il nome predefinito dell'origine è ServiceName.
C'è un modo per scrivere nel registro eventi:
O almeno, qualche altro registro predefinito di Windows, dove non devo registrare una fonte di eventi ?
ServiceBase.EventLog
. Il nome predefinito dell'origine è ServiceName.
Risposte:
Sì, c'è un modo per scrivere nel registro eventi che stai cercando. Non è necessario creare una nuova fonte, basta semplicemente usare quella esistente, che spesso ha lo stesso nome del nome dell'EventLog e anche, in alcuni casi come l'applicazione del registro eventi, può essere accessibile senza i privilegi di amministratore *.
* Altri casi, in cui non è possibile accedervi direttamente, sono il Security EventLog, ad esempio, a cui si accede solo dal sistema operativo.
Ho usato questo codice per scrivere direttamente nel registro eventi Applicazione:
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = "Application";
eventLog.WriteEntry("Log message example", EventLogEntryType.Information, 101, 1);
}
Come puoi vedere, l'origine EventLog è uguale al nome di EventLog. La ragione di ciò può essere trovata in Event Sources @ Windows Dev Center (ho in grassetto la parte che si riferisce al nome della fonte):
Ogni registro nella chiave Eventlog contiene sottochiavi chiamate origini eventi. La fonte dell'evento è il nome del software che registra l'evento. Spesso è il nome dell'applicazione o il nome di un sottocomponente dell'applicazione se l'applicazione è grande. È possibile aggiungere un massimo di 16.384 origini di eventi al registro.
È possibile utilizzare la classe EventLog, come spiegato in Procedura: scrivere nel registro eventi dell'applicazione (Visual C #) :
var appLog = new EventLog("Application");
appLog.Source = "MySource";
appLog.WriteEntry("Test log message");
Tuttavia, dovrai configurare questa fonte "MySource" usando i privilegi di amministratore:
Utilizzare WriteEvent e WriteEntry per scrivere eventi in un registro eventi. È necessario specificare una fonte di eventi per scrivere eventi; è necessario creare e configurare l'origine evento prima di scrivere la prima voce con l'origine.
Come indicato in MSDN (ad es. Https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog(v=vs.110).aspx ), il controllo di una fonte inesistente e la creazione di una fonte richiede admin privilegio.
È comunque possibile utilizzare l' origine "Applicazione" senza. Nel mio test in Windows 2012 Server r2, tuttavia ottengo la seguente voce di registro utilizzando l'origine "Applicazione":
Impossibile trovare la descrizione per ID evento xxxx dall'applicazione di origine. Il componente che genera questo evento non è installato sul computer locale o l'installazione è danneggiata. È possibile installare o riparare il componente sul computer locale. Se l'evento ha avuto origine su un altro computer, le informazioni sul display dovevano essere salvate con l'evento. Le seguenti informazioni sono state incluse con l'evento: {il mio messaggio di entrata evento} la risorsa messaggio è presente ma il messaggio non è stato trovato nella tabella string / message
Ho definito il seguente metodo per creare la fonte:
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;
}
Lo sto chiamando con currentAppName = AppDomain.CurrentDomain.FriendlyName
Potrebbe essere possibile utilizzare la classe EventLogPermission invece di questo tentativo / cattura, ma non sono sicuro che possiamo evitare la cattura.
È anche possibile creare la fonte esternamente, ad esempio in Powershell elevato:
New-EventLog -LogName Application -Source MyApp
Quindi, l'uso di "MyApp" nel metodo sopra NON genererà eccezioni e EventLog può essere creato con tale origine.
Questa è la classe logger che uso. Il metodo Log () privato ha EventLog.WriteEntry()
in esso, che è come si scrive effettivamente nel registro eventi. Sto includendo tutto questo codice qui perché è utile. Oltre alla registrazione, questa classe assicurerà anche che il messaggio non sia troppo lungo per scrivere nel registro eventi (troncerà il messaggio). Se il messaggio fosse troppo lungo, otterrai un'eccezione. Il chiamante può anche specificare l'origine. Se il chiamante non lo fa, questa classe otterrà la fonte. Spero che sia d'aiuto.
A proposito, puoi ottenere un ObjectDumper dal web. Non volevo postare tutto questo qui. Ho preso il mio da qui: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;
}
}
}
provare
System.Diagnostics.EventLog appLog = new System.Diagnostics.EventLog();
appLog.Source = "This Application's Name";
appLog.WriteEntry("An entry to the Application event log.");