"Debe crear y configurar el origen del evento antes de escribir la primera entrada con el origen".
Jerther
Parece que no puedo. Entonces, ¿hay un buen método alternativo para advertir que la aplicación no puede escribir en los registros de Windows? Un archivo plano parece bueno pero, ¿dónde? La carpeta de la aplicación aún necesitaría algunos permisos. Mi aplicación es un servicio de Windows.
Jerther
3
Si su aplicación es un servicio de Windows, se crea automáticamente un origen de eventos para usted. Puede acceder a través de ServiceBase.EventLog. El nombre predeterminado de la Fuente es ServiceName.
Mike Zboray
Respuestas:
236
Sí, hay una manera de escribir en el registro de eventos que está buscando. No necesita crear una nueva fuente, simplemente use la existente, que a menudo tiene el mismo nombre que el nombre de EventLog y también, en algunos casos, como la aplicación de registro de eventos, puede ser accesible sin privilegios administrativos *.
* Otros casos, en los que no puede acceder directamente, son Security EventLog, por ejemplo, al que solo accede el sistema operativo.
Utilicé este código para escribir directamente en la aplicación de registro de eventos:
using (EventLog eventLog =newEventLog("Application")){
eventLog.Source="Application";
eventLog.WriteEntry("Log message example",EventLogEntryType.Information,101,1);}
Como puede ver, la fuente de EventLog es la misma que el nombre de EventLog. La razón de esto se puede encontrar en Event Sources @ Windows Dev Center (en negrita la parte que se refiere al nombre de la fuente):
Cada registro en la clave Eventlog contiene subclaves llamadas orígenes de eventos. El origen del evento es el nombre del software que registra el evento. A menudo es el nombre de la aplicación o el nombre de un subcomponente de la aplicación si la aplicación es grande. Puede agregar un máximo de 16,384 orígenes de eventos al registro.
Pero el texto que citó dice que debe registrar el origen del evento bajo la clave de registro de eventos.
Raymond Chen
1
Lo que quise decir es que el nombre del registro de eventos suele ser el mismo nombre de la aplicación, por lo que puede registrar una entrada del registro de eventos directamente en el registro de eventos sin crear una nueva fuente. En negrita, el texto escrito para obtener más lecturas.
cloud120
3
Técnicamente, el acto de crear la clave de registro es registrar el origen del evento. Nombrar la clave después del nombre de la aplicación es una convención para evitar conflictos. Su respuesta es básicamente la misma que esta respuesta .
Raymond Chen
77
Gracias por su tiempo, Raymond Chen, estamos aquí para tratar de resolver o sugerir algo que pueda ayudar a otros. En este caso, creo que respondí la pregunta del tema: "¿Hay alguna forma de escribir en este registro de eventos: O al menos, algún otro registro predeterminado de Windows, donde no tengo que registrar un origen de eventos?". -> Respondí: Sí, lo compartí contigo. A pesar del hecho de que podría causar conflictos como dijiste, existe una manera.
cloud120
77
Está respondiendo la pregunta "¿Hay alguna manera de hacerlo sin registrar una fuente de evento?" y su respuesta dice "Cree esta clave de registro para registrar un origen de evento". También es idéntico a una respuesta existente.
var appLog =newEventLog("Application");
appLog.Source="MySource";
appLog.WriteEntry("Test log message");
Sin embargo, deberá configurar esta fuente "MySource" utilizando privilegios administrativos:
Use WriteEvent y WriteEntry para escribir eventos en un registro de eventos. Debe especificar un origen de evento para escribir eventos; debe crear y configurar el origen del evento antes de escribir la primera entrada con el origen.
Sin embargo, es posible utilizar la fuente "Aplicación" sin. Sin embargo, en mi prueba en Windows 2012 Server r2, obtengo la siguiente entrada de registro utilizando la fuente "Aplicación":
No se puede encontrar la descripción del evento ID xxxx de la aplicación de origen. El componente que genera este evento no está instalado en su computadora local o la instalación está dañada. Puede instalar o reparar el componente en la computadora local. Si el evento se originó en otra computadora, la información de la pantalla debía guardarse con el evento. La siguiente información se incluyó con el evento: {mi mensaje de entrada de evento} el recurso del mensaje está presente pero el mensaje no se encuentra en la tabla de cadena / mensaje
Definí el siguiente método para crear la fuente:
privatestringCreateEventSource(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 privilegeEventLog.CreateEventSource(eventSource,"Application");}}catch(SecurityException){
eventSource ="Application";}return eventSource;}
Lo estoy llamando con currentAppName = AppDomain.CurrentDomain.FriendlyName
Puede ser posible usar la clase EventLogPermission en lugar de este intento / captura, pero no estoy seguro de que podamos evitar la captura.
También es posible crear la fuente externamente, por ejemplo, en Powershell elevado:
New-EventLog-LogNameApplication-SourceMyApp
Luego, usar 'MyApp' en el método anterior NO generará una excepción y EventLog se puede crear con esa fuente.
Esta es la clase de registrador que uso. El método privado Log () tiene EventLog.WriteEntry(), que es cómo realmente escribe en el registro de eventos. Incluyo todo este código aquí porque es útil. Además del registro, esta clase también se asegurará de que el mensaje no sea demasiado largo para escribir en el registro de eventos (truncará el mensaje). Si el mensaje fuera demasiado largo, obtendría una excepción. La persona que llama también puede especificar la fuente. Si la persona que llama no lo hace, esta clase obtendrá la fuente. Espero eso ayude.
Por cierto, puede obtener un ObjectDumper de la web. No quería publicar todo eso aquí. Tengo el mío de aquí: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>publicstaticclassLogger{// 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.privateconstintMaxEventLogEntryLength=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>publicstaticstringSource{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>publicstaticvoidLogDebug(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>publicstaticvoidLogInformation(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>publicstaticvoidLogWarning(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>publicstaticvoidLogException(Exception ex,string source =""){if(ex ==null){thrownewArgumentNullException("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")]publicstaticvoidLogObjectDump(object theObject,string objectName,string source =""){constint 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);}privatestaticvoidLog(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);}}privatestaticstringGetSource(){// If the caller has explicitly set a source value, just use it.if(!string.IsNullOrWhiteSpace(Source)){returnSource;}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 =newStackTrace().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.privatestaticstringEnsureLogMessageLimit(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;}}}
Y este código muestra eso. ¿Qué hay de malo en compartir esto con él? ¿No podría ser útil para el OP y otros?
Bob Horn
55
No puede escribir en el registro de eventos sin crear un origen de eventos , por lo que este código no lo muestra.
CodeCaster
2
Todavía necesitaría crear la fuente del evento, pero publicó su respuesta antes de que se actualizara el título de la pregunta. Aún así, no sabía sobre el límite de longitud, gracias.
Jerther
-4
tratar
System.Diagnostics.EventLog appLog =newSystem.Diagnostics.EventLog();
appLog.Source="This Application's Name";
appLog.WriteEntry("An entry to the Application event log.");
ServiceBase.EventLog
. El nombre predeterminado de la Fuente es ServiceName.Respuestas:
Sí, hay una manera de escribir en el registro de eventos que está buscando. No necesita crear una nueva fuente, simplemente use la existente, que a menudo tiene el mismo nombre que el nombre de EventLog y también, en algunos casos, como la aplicación de registro de eventos, puede ser accesible sin privilegios administrativos *.
* Otros casos, en los que no puede acceder directamente, son Security EventLog, por ejemplo, al que solo accede el sistema operativo.
Utilicé este código para escribir directamente en la aplicación de registro de eventos:
Como puede ver, la fuente de EventLog es la misma que el nombre de EventLog. La razón de esto se puede encontrar en Event Sources @ Windows Dev Center (en negrita la parte que se refiere al nombre de la fuente):
fuente
Puede usar la clase EventLog, como se explica en Cómo: Escribir en el registro de eventos de la aplicación (Visual C #) :
Sin embargo, deberá configurar esta fuente "MySource" utilizando privilegios administrativos:
fuente
Como se indica en MSDN (por ejemplo, https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog(v=vs.110).aspx ), verificar una fuente no existente y crear una fuente requiere administración privilegio.
Sin embargo, es posible utilizar la fuente "Aplicación" sin. Sin embargo, en mi prueba en Windows 2012 Server r2, obtengo la siguiente entrada de registro utilizando la fuente "Aplicación":
Definí el siguiente método para crear la fuente:
Lo estoy llamando con currentAppName = AppDomain.CurrentDomain.FriendlyName
Puede ser posible usar la clase EventLogPermission en lugar de este intento / captura, pero no estoy seguro de que podamos evitar la captura.
También es posible crear la fuente externamente, por ejemplo, en Powershell elevado:
Luego, usar 'MyApp' en el método anterior NO generará una excepción y EventLog se puede crear con esa fuente.
fuente
Esta es la clase de registrador que uso. El método privado Log () tiene
EventLog.WriteEntry()
, que es cómo realmente escribe en el registro de eventos. Incluyo todo este código aquí porque es útil. Además del registro, esta clase también se asegurará de que el mensaje no sea demasiado largo para escribir en el registro de eventos (truncará el mensaje). Si el mensaje fuera demasiado largo, obtendría una excepción. La persona que llama también puede especificar la fuente. Si la persona que llama no lo hace, esta clase obtendrá la fuente. Espero eso ayude.Por cierto, puede obtener un ObjectDumper de la web. No quería publicar todo eso aquí. Tengo el mío de aquí:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Samples\1033\CSharpSamples.zip\LinqSamples\ObjectDumper
fuente
tratar
fuente