visual studio renombrar proyecto nombre directorio como carpeta cambiar archivo c# log4net

studio - renombrar archivo c#



¿Cómo puedo cambiar la ubicación del archivo programáticamente? (9)

Soy totalmente nuevo en Log4net.
Logré hacer algo añadiendo un archivo de configuración y un registro simple.
He codificado el valor para que sea "C:/temp/log.txt" pero esto no es lo suficientemente bueno.

Los registros deben ir a las carpetas especiales

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

y esta ruta cambia dependiendo de si está usando Windows Server 2008 o Windows XP o Vista, etc ...

¿Cómo puedo simplemente cambiar la ubicación del archivo en log4net mediante programación?

Esto es lo que he hecho:

<configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/> </configSections> <log4net> <root> <level value="DEBUG" /> <appender-ref ref="LogFileAppender" /> </root> <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender"> <param name="File" value="C:/temp/log.txt" /> <param name="AppendToFile" value="true" /> <rollingStyle value="Size" /> <maxSizeRollBackups value="10" /> <maximumFileSize value="10MB" /> <staticLogFileName value="true" /> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n" /> </layout> </appender> </log4net>

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

Solo necesito descubrir cómo puedo cambiar para registrar cosas en el lugar que quiero.

¿Alguna sugerencia? Muchas gracias


¿Qué tal un simple:

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

¿Por qué es tan complejo hacer algo realmente simple?


Como alternativa a hacer esto programáticamente, puede usar variables de entorno y patrones personalizables en el archivo de configuración. Vea esta respuesta a una pregunta similar .

Consulte "PatternString para la configuración basada en patrones" en las notas de la versión de Log4Net V1.2.10 .

Además, si está pensando en escribir en un directorio como Enviroment.SpecialFolder.CommonApplicationData, debe tener en cuenta lo siguiente:

  • ¿Todas las instancias de su aplicación para todos los usuarios tendrán acceso de escritura al archivo de registro? Por ejemplo, no creo que los no administradores puedan escribir en Enviroment.SpecialFolder.CommonApplicationData.

  • Contención si hay varias instancias de su aplicación (para el mismo o para diferentes usuarios) que están intentando hacer el mismo archivo. Puede usar el "modelo de bloqueo mínimo" (consulte para permitir que varios procesos escriban en el mismo archivo de registro, pero probablemente habrá un impacto en el rendimiento). O podría darle a cada proceso un archivo de registro diferente, por ejemplo, incluyendo la identificación del proceso en el nombre del archivo usando un patrón personalizable.


Encontré una mutación de este código en 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 string 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 = string.Format(@"C:/MySpecialFolder/{0}", fileInfo.Name); fa.File = logFileLocation; fa.ActivateOptions(); break; } }

Esto funciona para mí Nuestra aplicación necesita colocar el archivo de registro en una carpeta que contenga el número de versión de la aplicación basada en el archivo AssemblyInfo.cs.

Debería poder establecer el logFileLocation programáticamente (por ejemplo, puede usar Server.MapPath () si se trata de una aplicación web) para satisfacer sus necesidades.


Esto funcionó para mí:

<log4net> <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> .. <file value="${APPDATA}/MyApp/MyApp Client/logs/Log.txt"/> .. </log4net>

Si necesito escribir en carpetas especiales, encontré ayuda here (segundo y tercer ejemplo).

Editar:

Para responder OP. Esto funciona para el área ''todos los usuarios'':

... <file value="${ALLUSERSPROFILE}/MyApp/MyApp Client/logs/Log.txt"/> ...

Que normalmente es "C: / ProgramData" en las versiones más nuevas de Windows.

Ver estos también:
¿Cómo especificar la carpeta de datos de aplicación común para log4net? == https://.com/a/1889591/503621 y comentarios
&
https://superuser.com/q/405097/47628
https://.com/a/5550502/503621


Gran caso de uso para el filtro OfType<T> :

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

Si el nombre del archivo en la aplicación.config es log.txt esto cambiará la salida del logs/some_name_log.txt a logs/some_name_log.txt :

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

Para responder al problema original de OPs sería:

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


Para cambiar también la ruta del registro de errores (según la respuesta de JackAce):

private static void SetLogPath(string path, string 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; string logFileLocation = path; fa.File = logFileLocation; fa.ActivateOptions(); } else if (a.Name.Equals("ErrorFileAppender")) { log4net.Appender.FileAppender fa = (log4net.Appender.FileAppender)a; string logFileLocation = errorPath; fa.File = logFileLocation; fa.ActivateOptions(); } } } }


Parece que la respuesta de Peter no funciona para Log4net v1.2.10.0. Un método alternativo se describe here .

Básicamente, el método es implementar un convertidor de patrones personalizado para el archivo de configuración log4net.

Primero agregue esta clase a su proyecto:

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

A continuación, configure el parámetro Archivo de su FileAppender de la siguiente manera:

<file type="log4net.Util.PatternString"> <converter> <name value="folder" /> <type value="MyAppName.SpecialFolderPatternConverter,MyAppName" /> </converter> <conversionPattern value="%folder{CommonApplicationData}//SomeOtherFolder//log.txt" /> </file>

Básicamente, la %folder le dice que mire el convertidor llamado folder que lo apunta a la clase SpecialFolderPatternConverter. Luego llama a Convert en esa clase, pasando el valor enum de CommonApplicationData (o lo que sea).


Si tiene que implementar sistemas desconocidos y desea utilizar la solución simple de Philipp M, incluso con diferentes carpetas especiales, puede recuperar la ruta especial de la carpeta que desee y establecer una variable de env personalizada antes de cargar la configuración de log4net. string localData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); Environment.SetEnvironmentVariable("MY_FOLDER_DATA", localData); XmlConfigurator.Configure( ...

... solo para asegurarse de que la variable env existe y tiene el valor que desea.


log4net puede manejar esto por ti. Cualquier propiedad de apéndice de tipo cadena se puede formatear, en este caso, usando el log4net.Util.PatternString opción log4net.Util.PatternString . PatternString incluso admite la enumeración SpecialFolder que permite la siguiente configuración elegante:

<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" > <file type="log4net.Util.PatternString" value="%envFolderPath{CommonApplicationData}//test.txt" /> ... </appender>

Aquí hay una prueba unitaria que prueba el pudin:

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

La siguiente prueba verifica que log4net realmente escribe en el disco (lo que básicamente hace de esto una prueba de "integración", no una prueba de unidad, pero lo dejaremos así por ahora):

[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: sugiero usar la sintaxis de la propiedad compacta que se muestra en la muestra anterior. Eliminar todos esos "<nombre de propiedad =" hace que tu configuración sea mucho más legible.