Existe-t-il un moyen d'écrire dans ce journal des événements:
Ou du moins, un autre journal par défaut de Windows, où je n'ai pas à enregistrer une source d'événements ?
ServiceBase.EventLog
. Le nom par défaut de la source est le ServiceName.
Existe-t-il un moyen d'écrire dans ce journal des événements:
Ou du moins, un autre journal par défaut de Windows, où je n'ai pas à enregistrer une source d'événements ?
ServiceBase.EventLog
. Le nom par défaut de la source est le ServiceName.
Réponses:
Oui, il existe un moyen d'écrire dans le journal des événements que vous recherchez. Vous n'avez pas besoin de créer une nouvelle source, utilisez simplement celle existante, qui porte souvent le même nom que le nom de l'EventLog et qui, dans certains cas, comme l'application du journal des événements, peut être accessible sans privilèges administratifs *.
* D'autres cas, où vous ne pouvez pas y accéder directement, sont le Security EventLog, par exemple, qui n'est accessible que par le système d'exploitation.
J'ai utilisé ce code pour écrire directement dans l'application du journal des événements:
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = "Application";
eventLog.WriteEntry("Log message example", EventLogEntryType.Information, 101, 1);
}
Comme vous pouvez le voir, la source EventLog est la même que le nom de l'EventLog. La raison de cela peut être trouvée dans Event Sources @ Windows Dev Center (j'ai mis en gras la partie qui fait référence au nom de la source):
Chaque journal de la clé Eventlog contient des sous-clés appelées sources d'événements. La source de l'événement est le nom du logiciel qui enregistre l'événement. Il s'agit souvent du nom de l'application ou du nom d'un sous-composant de l'application si l'application est volumineuse. Vous pouvez ajouter un maximum de 16 384 sources d'événements au registre.
Vous pouvez utiliser la classe EventLog, comme expliqué sur Comment: écrire dans le journal des événements d'application (Visual C #) :
var appLog = new EventLog("Application");
appLog.Source = "MySource";
appLog.WriteEntry("Test log message");
Cependant, vous devrez configurer cette source "MySource" en utilisant les privilèges administratifs:
Utilisez WriteEvent et WriteEntry pour écrire des événements dans un journal des événements. Vous devez spécifier une source d'événements pour écrire des événements; vous devez créer et configurer la source d'événement avant d'écrire la première entrée avec la source.
Comme indiqué dans MSDN (par exemple, https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog(v=vs.110).aspx ), la vérification d'une source non existante et la création d'une source nécessitent un administrateur privilège.
Il est cependant possible d'utiliser la source "Application" sans. Dans mon test sous Windows 2012 Server r2, j'obtiens cependant l'entrée de journal suivante en utilisant la source "Application":
La description de l'ID d'événement xxxx de l'application source est introuvable. Soit le composant qui déclenche cet événement n'est pas installé sur votre ordinateur local, soit l'installation est endommagée. Vous pouvez installer ou réparer le composant sur l'ordinateur local. Si l'événement provenait d'un autre ordinateur, les informations d'affichage devaient être enregistrées avec l'événement. Les informations suivantes ont été incluses avec l'événement: {mon message d'entrée d'événement} la ressource de message est présente mais le message n'est pas trouvé dans la table de chaînes / messages
J'ai défini la méthode suivante pour créer la source:
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;
}
Je l'appelle avec currentAppName = AppDomain.CurrentDomain.FriendlyName
Il peut être possible d'utiliser la classe EventLogPermission au lieu de ce try / catch mais pas sûr que nous puissions éviter le catch.
Il est également possible de créer la source en externe, par exemple dans un Powershell élevé:
New-EventLog -LogName Application -Source MyApp
Ensuite, l'utilisation de «MyApp» dans la méthode ci-dessus ne générera PAS d'exception et le EventLog peut être créé avec cette source.
C'est la classe de journalisation que j'utilise. La méthode private Log () contient EventLog.WriteEntry()
, c'est ainsi que vous écrivez réellement dans le journal des événements. J'inclus tout ce code ici parce que c'est pratique. En plus de la journalisation, cette classe s'assurera également que le message n'est pas trop long pour être écrit dans le journal des événements (il tronquera le message). Si le message était trop long, vous obtiendrez une exception. L'appelant peut également spécifier la source. Si l'appelant ne le fait pas, cette classe obtiendra la source. J'espère que ça aide.
En passant, vous pouvez obtenir un ObjectDumper sur le Web. Je ne voulais pas poster tout ça ici. J'ai le mien d'ici: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;
}
}
}
essayer
System.Diagnostics.EventLog appLog = new System.Diagnostics.EventLog();
appLog.Source = "This Application's Name";
appLog.WriteEntry("An entry to the Application event log.");