Comment puis-je modifier l’emplacement du fichier par programmation?

Je suis totalement nouveau sur Log4net.
J’ai réussi à obtenir quelque chose en ajoutant un fichier de configuration et une consignation simple.
J’ai durci la valeur pour être "C:\temp\log.txt" mais ce n’est pas suffisant.

Les journaux doivent aller dans les dossiers spéciaux

 path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); 

et ce chemin change selon que vous utilisez Windows Server 2008 ou Windows XP ou Vista, etc.

Comment puis-je simplement modifier l’emplacement du fichier dans log4net par programmation?

C’est ce que j’ai fait:

  

 class Program { protected static readonly ILog log = LogManager.GetLogger(typeof(Program)); static void Main(ssortingng[] args) { log4net.Config.XmlConfigurator.Configure(); log.Warn("Log something"); path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); // How can I change where I log stuff? } } 

Juste besoin de comprendre comment je peux changer pour enregistrer des choses à l’endroit où je veux.

Aucune suggestion? Merci beaucoup

log4net peut gérer cela pour vous. Toute propriété appender de type chaîne peut être mise en forme, dans ce cas, à l’aide du gestionnaire d’ options log4net.Util.PatternSsortingng . PatternSsortingng prend même en charge l’énumération SpecialFolder qui active la configuration élégante suivante:

   ...  

Voici un test unitaire qui vérifie le pudding:

 [Test] public void Load() { XmlConfigurator.Configure(); var fileAppender = LogManager.GetRepository() .GetAppenders().First(appender => appender is RollingFileAppender); var expectedFile = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.CommonApplicationData), "test.txt"); Assert.That(fileAppender, Is.Not.Null & Has.Property("File").EqualTo(expectedFile)); } 

Le test suivant vérifie que log4net écrit réellement sur le disque (ce qui en fait un test d’intégration, pas un test unitaire, mais nous en restrons là pour l’instant):

 [Test] public void Log4net_WritesToDisk() { var expectedFile = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.CommonApplicationData), "test.txt"); if (File.Exists(expectedFile)) File.Delete(expectedFile); XmlConfigurator.Configure(); var log = LogManager.GetLogger(typeof (ConfigTest)); log.Info("Message from test"); LogManager.Shutdown(); Assert.That(File.ReadAllText(expectedFile), Text.Contains("Message from test")); } 

NB: Je suggère fortement d’utiliser la syntaxe de propriété compacte illustrée dans l’exemple ci-dessus. Supprimer tous ces “

J’ai trouvé une mutation de ce code dans les interwebs:

 XmlConfigurator.Configure(); log4net.Repository.Hierarchy.Hierarchy h = (log4net.Repository.Hierarchy.Hierarchy) LogManager.GetRepository(); foreach (IAppender a in h.Root.Appenders) { if (a is FileAppender) { FileAppender fa = (FileAppender)a; // Programmatically set this to the desired location here ssortingng logFileLocation = @"C:\MySpecialFolder\MyFile.log"; // Uncomment the lines below if you want to retain the base file name // and change the folder name... //FileInfo fileInfo = new FileInfo(fa.File); //logFileLocation = ssortingng.Format(@"C:\MySpecialFolder\{0}", fileInfo.Name); fa.File = logFileLocation; fa.ActivateOptions(); break; } } 

Cela fonctionne pour moi. Notre application doit placer le fichier journal dans un dossier contenant le numéro de version de l’application en fonction du fichier AssemblyInfo.cs.

Vous devriez pouvoir définir logFileLocation par programmation (par exemple, vous pouvez utiliser Server.MapPath () s’il s’agit d’une application Web) pour répondre à vos besoins.

On dirait que la réponse de Peter ne fonctionne pas pour Log4net v1.2.10.0. Une méthode alternative est décrite ici .

Fondamentalement, la méthode consiste à implémenter un convertisseur de modèle personnalisé pour le fichier de configuration log4net.

Ajoutez d’abord cette classe à votre projet:

 public class SpecialFolderPatternConverter : log4net.Util.PatternConverter { override protected void Convert(System.IO.TextWriter writer, object state) { Environment.SpecialFolder specialFolder = (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), base.Option, true); writer.Write(Environment.GetFolderPath(specialFolder)); } } 

Ensuite, configurez le paramètre File de votre FileAppender comme suit:

        

Fondamentalement, le %folder indique de regarder le convertisseur appelé folder qui le pointe vers la classe SpecialFolderPatternConverter. Il appelle ensuite Convert sur cette classe, en transmettant la valeur enum CommonApplicationData (ou autre).

Que diriez-vous d’un simple:

 XmlConfigurator.LogFullFilename = @"c:\ProgramData\MyApp\Myapp.log"; 

Pourquoi est-ce si complexe de faire une chose vraiment simple?

Cela a fonctionné pour moi:

    ..  ..  

Si vous avez besoin d’écrire dans des dossiers spéciaux, j’ai trouvé de l’aide ici (2ème et 3ème exemple).

Modifier:

Pour répondre à OP .. Cela fonctionne pour «tous les utilisateurs»:

  ...  ... 

Ce qui est normalement “C: \ ProgramData” dans les nouvelles versions de Windows.

Voir aussi:
Comment spécifier un dossier de données d’application commun pour log4net? == https://stackoverflow.com/a/1889591/503621 et commentaires
Et
https://superuser.com/q/405097/47628
https://stackoverflow.com/a/5550502/503621

Pour modifier également le chemin du journal des erreurs (en fonction de la réponse de JackAce):

 private static void SetLogPath(ssortingng path, ssortingng errorPath) { XmlConfigurator.Configure(); log4net.Repository.Hierarchy.Hierarchy h = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository(); foreach (var a in h.Root.Appenders) { if (a is log4net.Appender.FileAppender) { if (a.Name.Equals("LogFileAppender")) { log4net.Appender.FileAppender fa = (log4net.Appender.FileAppender)a; ssortingng logFileLocation = path; fa.File = logFileLocation; fa.ActivateOptions(); } else if (a.Name.Equals("ErrorFileAppender")) { log4net.Appender.FileAppender fa = (log4net.Appender.FileAppender)a; ssortingng logFileLocation = errorPath; fa.File = logFileLocation; fa.ActivateOptions(); } } } } 

Au lieu de le faire par programmation, vous pouvez utiliser des variables d’environnement et des modèles personnalisables dans le fichier de configuration. Voir cette réponse à une question similaire .

Regardez “PatternSsortingng pour la configuration basée sur les modèles ” dans les notes de version de Log4Net V1.2.10 .

Aussi, si vous envisagez d’écrire dans un répertoire tel que Enviroment.SpecialFolder.CommonApplicationData, vous devez prendre en compte:

  • Toutes les instances de votre application pour tous les utilisateurs auront-elles un access en écriture au fichier journal? Par exemple, je ne pense pas que les non-administrateurs pourront écrire dans Enviroment.SpecialFolder.CommonApplicationData.

  • Contention si plusieurs instances de votre application (pour le même utilisateur ou des utilisateurs différents) tentent le même fichier. Vous pouvez utiliser le “modèle de locking minimal” (voir http://logging.apache.org/log4net/release/config-examples.html pour permettre à plusieurs processus d’écrire dans le même fichier journal, mais cela aura probablement un impact sur les performances. Ou vous pouvez donner à chaque processus un fichier journal différent, par exemple en incluant l’identifiant du processus dans le nom du fichier en utilisant un modèle personnalisable.

Si vous devez déployer sur des systèmes inconnus et que vous souhaitez utiliser la solution simple de Philipp M même avec différents dossiers spéciaux, vous pouvez récupérer le chemin de dossier spécial souhaité et définir une variable env personnalisée avant de charger la configuration log4net. ssortingng localData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); Environment.SetEnvironmentVariable("MY_FOLDER_DATA", localData); XmlConfigurator.Configure( ...

… juste pour être sûr que la variable env existe et a la valeur que vous voulez.

Excellent cas d’utilisation pour le filtre OfType :

 ///  /// Applies a transformation to the filenames of all FileAppenders. ///  public static void ChangeLogFile(Func transformPath) { // iterate over all FileAppenders foreach (var fileAppender in LogManager.GetRepository().GetAppenders().OfType()) { // apply transformation to the filename fileAppender.File = transformPath(fileAppender.File); // notify the logging subsystem of the configuration change fileAppender.ActivateOptions(); } } 

Si le nom de fichier dans app.config est log.txt cela changera la sortie du journal en logs/some_name_log.txt :

 ChangeLogFile(path => Path.Combine("logs", $"some_name_{Path.GetFileName(path)}")); 

Pour répondre au problème original des OP qui serait:

 ChangeLogFile(path => Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), path));