"Você deve criar e configurar a fonte de eventos antes de escrever a primeira entrada com a fonte."
Jerther
Parece que não posso. Portanto, existe um bom método de fallback para avisar que o aplicativo não pode gravar nos logs do Windows? Um arquivo simples parece bom, mas onde? A pasta do aplicativo ainda precisaria de algumas permissões. Meu aplicativo é um serviço do Windows.
Jerther
3
Se o seu aplicativo for um Serviço do Windows, uma fonte de eventos será criada automaticamente para você. Você pode acessá-lo através ServiceBase.EventLog. O nome padrão da fonte é o ServiceName.
Mike Zboray
Respostas:
236
Sim, existe uma maneira de gravar no log de eventos que você está procurando. Você não precisa criar uma nova fonte, basta usar a existente, que geralmente tem o mesmo nome que o nome do EventLog e também, em alguns casos como o aplicativo de log de eventos, pode ser acessada sem privilégios administrativos *.
* Outros casos em que você não pode acessá-lo diretamente são o Security EventLog, por exemplo, que é acessado apenas pelo sistema operacional.
Eu usei esse código para gravar diretamente no aplicativo de log de eventos:
using (EventLog eventLog =newEventLog("Application")){
eventLog.Source="Application";
eventLog.WriteEntry("Log message example",EventLogEntryType.Information,101,1);}
Como você pode ver, a fonte EventLog é igual ao nome do EventLog. O motivo disso pode ser encontrado em Fontes de Eventos no Windows Dev Center (coloquei em negrito a parte que se refere ao nome da fonte):
Cada log na chave Eventlog contém subchaves chamadas fontes de eventos. A fonte do evento é o nome do software que registra o evento. Geralmente é o nome do aplicativo ou o nome de um subcomponente do aplicativo, se o aplicativo for grande. Você pode adicionar no máximo 16.384 fontes de eventos ao registro.
Mas o texto que você citou diz que é necessário registrar a fonte do evento na chave de log de eventos.
Raymond Chen
1
O que eu quis dizer é que o nome do log de eventos geralmente é o mesmo nome do aplicativo, por isso é possível registrar uma entrada do log de eventos diretamente no EventLog sem criar uma nova fonte. Coloquei o texto citado em negrito para outras leituras.
usar o seguinte comando
3
Tecnicamente, o ato de criar a chave do registro está registrando a fonte do evento. Nomear a chave após o nome do aplicativo é uma convenção para evitar conflitos. Sua resposta é basicamente a mesma que esta resposta .
Raymond Chen
7
Obrigado pelo seu tempo Raymond Chen, estamos aqui para tentar resolver ou sugerir algo que possa ajudar outras pessoas. Nesse caso, acredito que respondi à pergunta do tópico: "Existe uma maneira de gravar neste log de eventos: ou pelo menos em algum outro log padrão do Windows, onde não preciso registrar uma fonte de eventos?". -> Eu respondi: Sim, e eu compartilhei com você. Apesar do fato de que isso pode causar conflitos, como você disse, existe uma maneira.
cloud120
7
Você está respondendo à pergunta "Existe uma maneira de fazer isso sem registrar uma fonte de evento?" e sua resposta diz "Crie esta chave do Registro para registrar uma fonte de eventos". Também é idêntico a uma resposta existente.
var appLog =newEventLog("Application");
appLog.Source="MySource";
appLog.WriteEntry("Test log message");
No entanto, você precisará configurar esta fonte "MySource" usando privilégios administrativos:
Use WriteEvent e WriteEntry para gravar eventos em um log de eventos. Você deve especificar uma fonte de eventos para gravar eventos; você deve criar e configurar a fonte de eventos antes de gravar a primeira entrada com a fonte.
Este é o problema que eu tenho: Eu não posso criar a fonte, porque eu não tenho esses privilégios, mas eu ainda preciso de log que problema em algum lugar
No entanto, é possível usar a fonte "Aplicativo" sem. No meu teste no Windows 2012 Server r2, no entanto, recebo a seguinte entrada de log usando a fonte "Aplicativo":
A descrição para identificação de evento xxxx do aplicativo de origem não foi encontrada. O componente que gera esse evento não está instalado no computador local ou a instalação está corrompida. Você pode instalar ou reparar o componente no computador local. Se o evento se originou em outro computador, as informações de exibição precisavam ser salvas com o evento. As seguintes informações foram incluídas no evento: {minha mensagem de entrada de evento} o recurso de mensagem está presente, mas a mensagem não foi encontrada na tabela de cadeia / mensagem
Eu defini o seguinte método para criar a fonte:
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;}
Estou chamando-o com currentAppName = AppDomain.CurrentDomain.FriendlyName
Pode ser possível usar a classe EventLogPermission em vez desta tentativa / captura, mas não temos certeza de que podemos evitar a captura.
Também é possível criar a fonte externamente, por exemplo, no Powershell elevado:
New-EventLog-LogNameApplication-SourceMyApp
Em seguida, usar 'MyApp' no método acima NÃO gerará exceção e o EventLog poderá ser criado com essa fonte.
Esta é a classe de logger que eu uso. O método Log () privado contém EventLog.WriteEntry(), é assim que você realmente escreve no log de eventos. Estou incluindo todo esse código aqui porque é útil. Além do log, essa classe também garantirá que a mensagem não seja muito longa para gravar no log de eventos (truncará a mensagem). Se a mensagem for muito longa, você receberá uma exceção. O chamador também pode especificar a fonte. Se o chamador não atender, essa classe receberá a fonte. Espero que ajude.
A propósito, você pode obter um ObjectDumper na Web. Eu não queria postar tudo isso aqui. Eu tenho o meu daqui: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;}}}
E esse código mostra isso. Qual é o mal em compartilhar isso com ele? Não poderia ser útil para o OP e outros?
Bob Horn
5
Você não pode gravar no log de eventos sem criar uma fonte de eventos , portanto esse código não mostra isso.
CodeCaster 8/09/14
2
Eu ainda precisaria criar a fonte do evento, mas você postou sua resposta antes que o título da pergunta fosse atualizado. Ainda assim, eu não sabia sobre o limite de comprimento, obrigado.
Jerther
-4
experimentar
System.Diagnostics.EventLog appLog =newSystem.Diagnostics.EventLog();
appLog.Source="This Application's Name";
appLog.WriteEntry("An entry to the Application event log.");
ServiceBase.EventLog
. O nome padrão da fonte é o ServiceName.Respostas:
Sim, existe uma maneira de gravar no log de eventos que você está procurando. Você não precisa criar uma nova fonte, basta usar a existente, que geralmente tem o mesmo nome que o nome do EventLog e também, em alguns casos como o aplicativo de log de eventos, pode ser acessada sem privilégios administrativos *.
* Outros casos em que você não pode acessá-lo diretamente são o Security EventLog, por exemplo, que é acessado apenas pelo sistema operacional.
Eu usei esse código para gravar diretamente no aplicativo de log de eventos:
Como você pode ver, a fonte EventLog é igual ao nome do EventLog. O motivo disso pode ser encontrado em Fontes de Eventos no Windows Dev Center (coloquei em negrito a parte que se refere ao nome da fonte):
fonte
Você pode usar a classe EventLog, conforme explicado em Como: gravar no log de eventos do aplicativo (Visual C #) :
No entanto, você precisará configurar esta fonte "MySource" usando privilégios administrativos:
fonte
Conforme declarado no MSDN (por exemplo, https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog(v=vs.110).aspx ), verificar uma fonte inexistente e criar uma fonte requer administração privilégio.
No entanto, é possível usar a fonte "Aplicativo" sem. No meu teste no Windows 2012 Server r2, no entanto, recebo a seguinte entrada de log usando a fonte "Aplicativo":
Eu defini o seguinte método para criar a fonte:
Estou chamando-o com currentAppName = AppDomain.CurrentDomain.FriendlyName
Pode ser possível usar a classe EventLogPermission em vez desta tentativa / captura, mas não temos certeza de que podemos evitar a captura.
Também é possível criar a fonte externamente, por exemplo, no Powershell elevado:
Em seguida, usar 'MyApp' no método acima NÃO gerará exceção e o EventLog poderá ser criado com essa fonte.
fonte
Esta é a classe de logger que eu uso. O método Log () privado contém
EventLog.WriteEntry()
, é assim que você realmente escreve no log de eventos. Estou incluindo todo esse código aqui porque é útil. Além do log, essa classe também garantirá que a mensagem não seja muito longa para gravar no log de eventos (truncará a mensagem). Se a mensagem for muito longa, você receberá uma exceção. O chamador também pode especificar a fonte. Se o chamador não atender, essa classe receberá a fonte. Espero que ajude.A propósito, você pode obter um ObjectDumper na Web. Eu não queria postar tudo isso aqui. Eu tenho o meu daqui:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Samples\1033\CSharpSamples.zip\LinqSamples\ObjectDumper
fonte
experimentar
fonte