J'ai un service Windows avec un app.config
et un log4net.config
.
app.config
:
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net configSource="log4net.config" />
log4net.config
:
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="D:\Projects\Integration\Interface Module\bin\Logs\MyFirstLogger.log"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="1MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="LogFileAppender" />
</root>
</log4net>
J'ai aussi ajouté ceci dans AssemblyInfo.cs
:
[Assembly: log4net.Config.XmlConfigurator(Watch = true)]
Et dans un de mes cours, j'ai:
private readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
et
_log.Info(content);
J'ai donné à à tous les utilisateurs des autorisations complètes sur mon dossier Journaux.
Mon dossier bin (depuis lequel le service est exécuté) a à la fois mon app.config
et log4net.config
.
Mais aucun fichier de journalisation n'a été généré. Quels paramètres ai-je manqués?
Mis à jour le 4 mars 2014
Si vous utilisez un fichier de configuration distinct, comme je l'ai fait (log4net.config), n'oubliez pas de définir le paramètre Copy to output directory
sur Copy always
dans l'explorateur de solutions.
Par sa conception, Log4Net est
fail-stop, nous voulons dire que log4net ne lève pas d'exceptions inattendues au moment de l'exécution provoquant potentiellement le blocage de votre application
Il est donc très difficile de comprendre ce qui cause le problème.
Comment activer le débogage interne de log4net?
FROM FAQ - http://logging.Apache.org/log4net/release/faq.html
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="log4net.Internal.Debug" value="true"/> </appSettings> </configuration>
Ce paramètre est lu immédiatement au démarrage et tous les messages de débogage internes seront émis.
Voici donc une classe personnalisée que j'ai créée pour log4Net - car le fichier de configuration était très déroutant, j'ai créé cette classe d'assistance
Log4NetFileHelper log = new Log4NetFileHelper(); log.Init(); //Initialize log.AddConsoleLogging(); //Add Console Logging log.AddFileLogging(Path.Combine(AssemblyDirectory, "BatchConsole.log")); log.AddFileLogging(Path.Combine(AssemblyDirectory,"BatchConsole_error.log"),log4net.Core.Level.Error);
Définissez cette propriété sur True log4net.Util.LogLog.InternalDebugging = true;
public class Log4NetFileHelper
{
private string DEFAULT_LOG_FILENAME=string.Format("application_log_{0}.log",DateTime.Now.ToString("yyyyMMMdd_hhmm"));
Logger root;
public Log4NetFileHelper()
{
}
public virtual void Init()
{
root = ((Hierarchy)LogManager.GetRepository()).Root;
//root.AddAppender(GetConsoleAppender());
//root.AddAppender(GetFileAppender(sFileName));
root.Repository.Configured = true;
}
#region Public Helper Methods
#region Console Logging
public virtual void AddConsoleLogging()
{
ConsoleAppender C = GetConsoleAppender();
AddConsoleLogging(C);
}
public virtual void AddConsoleLogging(ConsoleAppender C)
{
root.AddAppender(C);
}
#endregion
#region File Logging
public virtual FileAppender AddFileLogging()
{
return AddFileLogging(DEFAULT_LOG_FILENAME);
}
public virtual FileAppender AddFileLogging(string sFileFullPath)
{
return AddFileLogging(sFileFullPath, log4net.Core.Level.All);
}
public virtual FileAppender AddFileLogging(string sFileFullPath, log4net.Core.Level threshold)
{
return AddFileLogging(sFileFullPath, threshold,true);
}
public virtual FileAppender AddFileLogging(string sFileFullPath, log4net.Core.Level threshold, bool bAppendfile)
{
FileAppender appender = GetFileAppender(sFileFullPath, threshold , bAppendfile);
root.AddAppender(appender);
return appender;
}
public virtual SmtpAppender AddSMTPLogging(string smtpHost, string From, string To, string CC, string subject, log4net.Core.Level threshhold)
{
SmtpAppender appender = GetSMTPAppender(smtpHost, From, To, CC, subject, threshhold);
root.AddAppender(appender);
return appender;
}
#endregion
public log4net.Appender.IAppender GetLogAppender(string AppenderName)
{
AppenderCollection ac = ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root.Appenders;
foreach(log4net.Appender.IAppender appender in ac){
if (appender.Name == AppenderName)
{
return appender;
}
}
return null;
}
public void CloseAppender(string AppenderName)
{
log4net.Appender.IAppender appender = GetLogAppender(AppenderName);
CloseAppender(appender);
}
private void CloseAppender(log4net.Appender.IAppender appender)
{
appender.Close();
}
#endregion
#region Private Methods
private SmtpAppender GetSMTPAppender(string smtpHost, string From, string To, string CC, string subject, log4net.Core.Level threshhold)
{
SmtpAppender lAppender = new SmtpAppender();
lAppender.Cc = CC;
lAppender.To = To;
lAppender.From = From;
lAppender.SmtpHost = smtpHost;
lAppender.Subject = subject;
lAppender.BufferSize = 512;
lAppender.Lossy = false;
lAppender.Layout = new
log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
lAppender.Threshold = threshhold;
lAppender.ActivateOptions();
return lAppender;
}
private ConsoleAppender GetConsoleAppender()
{
ConsoleAppender lAppender = new ConsoleAppender();
lAppender.Name = "Console";
lAppender.Layout = new
log4net.Layout.PatternLayout(" %message %n");
lAppender.Threshold = log4net.Core.Level.All;
lAppender.ActivateOptions();
return lAppender;
}
/// <summary>
/// DETAILED Logging
/// log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
///
/// </summary>
/// <param name="sFileName"></param>
/// <param name="threshhold"></param>
/// <returns></returns>
private FileAppender GetFileAppender(string sFileName , log4net.Core.Level threshhold ,bool bFileAppend)
{
FileAppender lAppender = new FileAppender();
lAppender.Name = sFileName;
lAppender.AppendToFile = bFileAppend;
lAppender.File = sFileName;
lAppender.Layout = new
log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
lAppender.Threshold = threshhold;
lAppender.ActivateOptions();
return lAppender;
}
//private FileAppender GetFileAppender(string sFileName)
//{
// return GetFileAppender(sFileName, log4net.Core.Level.All,true);
//}
#endregion
private void ConfigureLog(string sFileName)
{
}
}
Veuillez noter que lorsque le processus est exécuté en tant que service Windows, Environment.CurrentDirectory sera "C:\Windows\system32".
Donc, si vous mettez le fichier de configuration log4net (log4net.config) à côté de votre * .exe, vous pouvez utiliser le code suivant pour configurer log4net.
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
XmlConfigurator.Configure(new FileInfo(Path.Combine(assemblyFolder, "log4net.config")));
Voici la config qui fonctionne pour moi.
AssemblyInfo.cs
[Assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4net.config", Watch = true)]
Log4net.Config
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="C:\TEMP\Logs.txt"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock,log4net" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="1MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="LogFileAppender" />
</root>
</log4net>
Code C #
private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(typeof(class_name));
J'ai cette configuration dans le projet de bibliothèque de classe C # et tous les autres projets utilisent cette référence de projet pour consigner les exceptions.
Après vérification et revérifier ... :-)
Il suffit d’appeler XmlConfigurator.Configure();
avant de créer le consignateur (une seule fois).
Content de vous aider,
Ofir
Lorsque vous dites "Tous les utilisateurs" ont des autorisations complètes sur le répertoire des journaux, cela inclut-il les comptes de service?
Vérifiez que LocalService, NetworkService, LocalSystem, etc. ont des autorisations (en fonction du contexte dans lequel le service est exécuté).
En outre, en supposant que vous disposiez d'un faisceau pour exécuter le service en tant qu'application, la journalisation fonctionne-t-elle lorsqu'elle est exécutée en tant qu'utilisateur?
Si l'application ne fonctionne pas correctement, vous avez un problème avec la configuration log4net (que d'autres réponses ont tenté de résoudre).
Désolé si certaines d'entre elles semblent évidentes, mais voici ce que je vérifierais:
Assurez-vous que les propriétés de votre fichier log4net.config Copier vers la sortie sont définies sur Copier toujours, vérifiez en recherchant le fichier dans votre répertoire bin
Notez également à partir de la documentation log4net liée aux propriétés de AssemblyInfo.cs:
L’utilisation d’attributs peut être une méthode plus claire pour définir le lieu de chargement de la configuration de l’application. Cependant, cela vaut la peine notant que les attributs sont purement passifs. Ce ne sont que des informations . Par conséquent, si vous utilisez des attributs de configuration, vous devez appeler log4net pour lui permettre de lire les attributs. Un simple appel à LogManager.GetLogger provoquera les attributs sur l'assembly appelant être lu et traité. Par conséquent, il est impératif de faire un enregistrement de l'appel le plus tôt possible lors du démarrage de l'application, et certainement avant que des assemblages externes aient été chargés et invoqué .
Pour résoudre ce problème, vous pouvez essayer de passer de la propriété de niveau d'assemblage à un appel de configuration explicite.
XmlConfigurator.Configure ();
devrait être suffisant.
Je fais toujours de log4net.config un fichier de configuration complet, en commençant par
<? xml version = "1.0" encoding = "utf-8"?> <configuration> <configSections> <section name = "log4net" type = "log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> </ configSections> <log4net> ... </ log4net> </ configuration>
Dans app.config, vous n'avez besoin d'aucun élément lié à log4net tant que votre fichier de configuration est log4net.config.
Pourriez-vous s'il vous plaît télécharger votre application afin que je puisse la déboguer moi-même?
quelques-uns, je recommande de vérifier:
remplace tous les "\" dans votre chemin de fichier par "\"
mettre toute la configuration log4net incorporée dans le fichier de configuration de l'application.
activer le débogage de log4net .__ ( voir ici )
essayez une configuration différente. juste obtenir un exemple de configuration quelque part sur Internet.
juste pour être sûr, je donnerais un maximum d'autorisations pour tous les utilisateurs à votre répertoire de journalisation
essayez de désinstaller le service et réinstallez-le.
log4net s'exécute sous les privilèges de l'utilisateur actif. Assurez-vous que l'utilisateur actif dispose des droits pour créer/modifier/supprimer le fichier texte spécifié.
si vous avez un fichier séparé pour log4net.config. Avez-vous défini la propriété suivante:
Copier dans le répertoire de sortie = Copier toujours
Le service Windows avec connexion système n'a pas accès à tous les répertoires présents . Essayez donc de vous connecter à "C:\Utilisateurs\Public\AppData" . Cela a fonctionné pour moi
J'ai vu votre code a un problème mineur dans AssemblyInfo.cs.
remplacez votre code par:
où {{folder_path}} est le chemin de votre log4net.config