프로그래밍 방식으로 파일 위치를 어떻게 변경할 수 있습니까?
저는 Log4net을 처음 사용합니다.
구성 파일과 간단한 로깅을 추가하여 작업을 수행했습니다.
값을 하드 코딩 "C:\temp\log.txt"
했지만 이것만으로는 충분하지 않습니다.
로그는 특수 폴더로 이동해야합니다.
path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
이 경로는 Windows Server 2008 또는 Windows XP 또는 Vista 등을 사용하는지 여부에 따라 변경됩니다.
프로그래밍 방식으로 log4net에서 파일의 위치를 어떻게 변경할 수 있습니까?
이것이 내가 한 일입니다.
<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?
}
}
내가 원하는 곳에 기록하도록 변경하는 방법을 알아 내면됩니다.
어떤 제안? 고마워
log4net이이를 처리 할 수 있습니다. string 유형의 모든 appender 속성은이 경우 log4net.Util.PatternString 옵션 핸들러를 사용하여 형식을 지정할 수 있습니다 . PatternString 은 다음과 같은 우아한 구성을 가능하게 하는 SpecialFolder 열거 형도 지원합니다 .
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" >
<file type="log4net.Util.PatternString"
value="%envFolderPath{CommonApplicationData}\\test.txt" />
...
</appender>
푸딩을 증명하는 단위 테스트는 다음과 같습니다.
[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));
}
다음 테스트는 log4net이 실제로 디스크에 쓰는지 확인합니다 (기본적으로이를 단위 테스트가 아닌 "통합"테스트로 만들지 만 지금은 그대로 둡니다).
[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 : 위의 샘플에서 보여준 압축 속성 구문을 사용하는 것이 좋습니다. "<property name ="을 모두 제거하면 구성을 훨씬 더 읽기 쉽게 만들 수 있습니다.
인터 웹에서이 코드의 변형을 발견했습니다.
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;
}
}
이것은 나를 위해 작동합니다. 애플리케이션은 AssemblyInfo.cs 파일을 기반으로하는 앱의 버전 번호가 포함 된 폴더에 로그 파일을 저장해야합니다.
필요에 맞게 logFileLocation을 프로그래밍 방식으로 설정할 수 있어야합니다 (예 : 웹 애플리케이션 인 경우 Server.MapPath ()를 사용할 수 있음).
과 같은 베드로의 대답은 Log4net v1.2.10.0 작동하지 않습니다. 여기에 대체 방법이 설명되어 있습니다 .
기본적으로 방법은 log4net 구성 파일에 대한 사용자 정의 패턴 변환기를 구현하는 것입니다.
먼저 프로젝트에이 클래스를 추가하십시오.
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));
}
}
그런 다음 FileAppender의 File 매개 변수를 다음과 같이 설정합니다.
<file type="log4net.Util.PatternString">
<converter>
<name value="folder" />
<type value="MyAppName.SpecialFolderPatternConverter,MyAppName" />
</converter>
<conversionPattern value="%folder{CommonApplicationData}\\SomeOtherFolder\\log.txt" />
</file>
기본적으로는 SpecialFolderPatternConverter 클래스를 가리키는 %folder
변환기를 보도록 지시합니다 folder
. 그런 다음 Convert
해당 클래스 를 호출 하여 CommonApplicationData (또는 기타) 열거 형 값을 전달합니다.
간단한 방법 :
XmlConfigurator.LogFullFilename = @"c:\ProgramData\MyApp\Myapp.log";
정말 간단한 일을하는 것이 왜 그렇게 복잡한가요?
이것은 나를 위해 일했습니다.
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
..
<file value="${APPDATA}\MyApp\MyApp Client\logs\Log.txt"/>
..
</log4net>
특수 폴더에 쓸 필요가있는 경우 여기 에서 도움말을 찾았 습니다 (두 번째 및 세 번째 예).
편집하다:
OP에 대답하려면 .. 이것은 '모든 사용자'영역에서 작동합니다.
...
<file value="${ALLUSERSPROFILE}\MyApp\MyApp Client\logs\Log.txt"/>
...
새 버전의 Windows에서는 일반적으로 "C : \ ProgramData"입니다.
See these too:
How to specify common application data folder for log4net? == https://stackoverflow.com/a/1889591/503621 and comments
&
https://superuser.com/q/405097/47628
https://stackoverflow.com/a/5550502/503621
To also change the error log's path (based on JackAce's answer):
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();
}
}
}
}
JackAce's answer, just more concise using Linq:
C#
XmlConfigurator.Configure();
var appender = (LogManager.GetRepository() as Hierarchy).Root.Appenders
.OfType<FileAppender>()
.First();
appender.File = logPath;
appender.ActivateOptions();
VB.NET
XmlConfigurator.Configure()
Dim appender = CType(LogManager.GetRepository(), Hierarchy).Root.Appenders _
.OfType(FileAppender)() _
.First()
appender.File = logPath
appender.ActivateOptions()
Great use case for LINQs OfType<T>
filter:
/// <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();
}
}
If the filename in the app.config is log.txt
this will change the log output to logs/some_name_log.txt
:
ChangeLogFile(path => Path.Combine("logs", $"some_name_{Path.GetFileName(path)}"));
To Answer the OPs original problem that would be:
ChangeLogFile(path => Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), path));
In the current version of Log4Net (2.0.8.0) you could simply use <file value="${ProgramData}\myFolder\LogFiles\" />
for C:\ProgramData\..
and ${LocalAppData}
for C:\Users\user\AppData\Local\
As an alternative to doing this programatically, you can use environment variables and customizable patterns in the configuration file. See this response to a similar question.
Look at "PatternString for pattern based configuration" in the Log4Net V1.2.10 release notes.
Also if you are thinking of writing to a directory such as Enviroment.SpecialFolder.CommonApplicationData you need to consider:
Will all instances of your application for all users have write access to the log file? E.g. I don't believe non-administrators will be able to write to Enviroment.SpecialFolder.CommonApplicationData.
Contention if multiple instances of your application (for the same or different users) are attempting to the same file. You can use the "minimal locking model" (see http://logging.apache.org/log4net/release/config-examples.html to allow multiple processes to write to the same log file, but there probably will be a performance impact. Or you could give each process a different log file, e.g. by including the process id in the filename using a customizable pattern.
If you have to deploy to unknown systems and you want to use the simple solution by Philipp M even with different special folders you can retrieve the special folder path you want and set a custom env variable before loading the log4net configuration. string localData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); Environment.SetEnvironmentVariable("MY_FOLDER_DATA", localData); XmlConfigurator.Configure( ...
... just to be sure the env variable exists and has the value you want.
참고URL : https://stackoverflow.com/questions/1535736/how-can-i-change-the-file-location-programmatically
'Programing' 카테고리의 다른 글
React JSX 파일에서“Undefined의 'createElement'속성을 읽을 수 없습니다. (0) | 2020.10.29 |
---|---|
매우 긴 문자열을 자동 줄 바꿈 (0) | 2020.10.29 |
java : 한 유형에서 다른 유형으로 변수를 동적으로 캐스팅하려면 어떻게해야합니까? (0) | 2020.10.29 |
Eclipse는 자동으로 저장 (0) | 2020.10.29 |
양식이로드 될 때 comboBox의 selectedIndexChanged 이벤트가 시작되지 않도록 중지 (0) | 2020.10.29 |