2014-09-08 15 views
73

C'è un modo per scrivere a questo registro eventi:Scrivici applicazioni di Windows Event Log

enter image description here

O almeno, qualche altro registro predefinito di Windows, dove non c'è bisogno di registrare un evento fonte?

+4

http://msdn.microsoft.com/en-us/library/42ste2f3%28v=vs.90%29.aspx –

+0

http://support.microsoft.com/kb/307024/en-us – Albi

+1

" È necessario creare e configurare l'origine degli eventi prima di scrivere la prima voce con la fonte. " – Jerther

risposta

113

Sì, c'è un modo di 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 del EventLog e, in alcuni casi, come l'applicazione del registro eventi, può essere accessibile senza privilegi amministrativi *.

* 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 al registro eventi applicazioni:

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

Come si può vedere, la fonte EventLog è lo stesso nome del EventLog. La ragione di questo può essere trovato in Event Sources @ Windows Dev Center (I grassetto la parte che si riferisce al nome della sorgente):

Ogni registro nella chiave di registro eventi contiene le sottochiavi denominate 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 è di grandi dimensioni. È possibile aggiungere un massimo di 16.384 fonti di eventi al registro.

+1

Ma il testo che hai citato dice che devi registrare la fonte dell'evento sotto il tasto Registro eventi. –

+0

Ciò che intendevo è che il nome del registro eventi è spesso lo stesso nome dell'applicazione, quindi è possibile registrare una voce del registro eventi direttamente in EventLog senza creare una nuova origine. Ho audito il testo citato per ulteriori letture. – cloud120

+1

Tecnicamente l'atto di creare la chiave di registro * è * la registrazione della fonte dell'evento. Denominare la chiave dopo il nome dell'applicazione è una convenzione per evitare conflitti. La tua risposta è fondamentalmente la stessa di [questa risposta] (http://stackoverflow.com/a/25725326/902497). –

7

È possibile utilizzare la classe EventLog, come spiegato a How to: Write to the Application Event Log (Visual C#):

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

Tuttavia, è necessario configurare questo fonte "MYSOURCE" utilizzando privilegi di amministratore:

Usa WriteEvent e WriteEntry per scrivere eventi in un registro eventi. Devi specificare una fonte di eventi per scrivere eventi; è necessario creare e configurare la sorgente di eventi prima di scrivere la prima voce con la fonte.

+2

Questo è il problema che ho: non riesco a creare l'origine perché non ho questi privilegi, ma devo comunque registrare il problema da qualche parte – Jerther

+2

Quindi utilizzare un programma di installazione (http://stackoverflow.com/questions/1484605/does-one-need-to-manual-create-a-windows-event-log-source-when-installation-a-wi) o accedere al file. – CodeCaster

+1

Grazie. Questo mi ha portato a questa altra domanda SO: http://stackoverflow.com/questions/3930529/does-event-logger-in-c-sharp-needs-admin-privileges-to-write-logs-into-windows-e – Jerther

-3

provare

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

questo ha bisogno di registrare una fonte di eventi e quindi non risponde alla domanda. scusa. – Jerther

+0

L'idea principale di questa domanda è usare la fonte di eventi "Applicazione". – rcarrillopadron

6

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é è comodo. Oltre alla registrazione, questa classe si accerterà anche che il messaggio non sia troppo lungo per scrivere nel registro eventi (troncherà il messaggio). Se il messaggio fosse troppo lungo, avresti ottenuto un'eccezione. Il chiamante può anche specificare la fonte. Se il chiamante no, questa classe otterrà la fonte. Spero che sia d'aiuto.

A proposito, è possibile ottenere un ObjectDumper dal web. Non volevo postare tutto questo qui. Ho ottenuto 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; 
     } 
    } 
} 
+3

E questo codice lo dimostra. Qual è il danno nel condividere questo con lui? Non potrebbe essere utile all'OP e ad altri? –

+4

Non è possibile scrivere nel registro eventi ** senza creare un'origine evento **, quindi questo codice non lo mostra. – CodeCaster

+1

Avrei ancora bisogno di creare la fonte dell'evento ma hai postato il tuo anwser prima che il titolo della domanda fosse aggiornato. Eppure, non sapevo del limite di lunghezza, grazie. – Jerther

2

Come indicato in MSDN (ad esempio https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog(v=vs.110).aspx), il controllo di una fonte non esistente e la creazione di una fonte richiede il privilegio di amministratore.

È tuttavia possibile utilizzare l'origine "" Applicazione " senza. Nella mia prova sotto Windows 2012 Server R2, ho comunque ottenere la seguente voce di registro utilizzando fonte "Applicazione":

La descrizione per l'ID evento xxxx dalla applicazione di origine non può essere trovato. Il componente che solleva questo evento non è installato sul computer locale o l'installazione è corrotta. È possibile installare o riparare il componente sul computer locale. Se l'evento è stato originato su un altro computer, le informazioni di visualizzazione dovevano essere salvate con l'evento. Le seguenti informazioni è stato incluso con l'evento: {mio evento messaggio di ingresso} la risorsa messaggio è presente ma il messaggio non è stato trovato nella tabella di stringhe/messaggio

ho definito il seguente metodo per creare l'origine :

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; 
    } 

sto chiamando con currentAppName = AppDomain.CurrentDomain.FriendlyName

potrebbe essere possibile utilizzare la classe EventLogPermission al posto di questo try/catch, ma non certo che possiamo evitare la cattura.

È inoltre possibile creare l'origine esternamente, per esempio in elevata Powershell:

New-EventLog -LogName Application -Source MyApp 

Poi, usando 'MyApp' nel metodo di cui sopra non genererà eccezione e l'EventLog può essere creato con quella sorgente.

Problemi correlati