Error while compiling view
Error compiling template: views/devices.cshtml
Errors:
[CS0234] Line: 3 Column: 27 - The type or namespace name 'Services' does
not exist in the namespace 'Rioxo.Companion'
(are you missing an assembly reference?)
Details:
#using System
#using System.Collections.Generic
#using Rioxo.Companion.Services <---
web.config
<razor disableAutoIncludeModelNamespace="false">
<assemblies>
<add assembly="Server32" />
<add assembly="Rioxo.Companion.Services" />
</assemblies>
<namespaces>
<add namespace="Rioxo.Companion.Server" />
<add namespace="Rioxo.Companion.Services" />
</namespaces>
</razor>
What could be the problem here?
Edit: the original problem was solved by putting the configuration in the correct .config file, for future reference, adding here you can also implement your own IRazorConfiguration which Nancy will automatically pick up, this means you don't need any .config registraion at all.
Example:
public class RazorConfig : IRazorConfiguration
{
public IEnumerable<string> GetAssemblyNames()
{
yield return "MyWebsite.Web";
yield return "MyWebsite.Models";
yield return "Sandra.SimpleValidator";
yield return "ServiceStack.Text";
}
public IEnumerable<string> GetDefaultNamespaces()
{
yield return "Nancy.Validation";
yield return "System.Globalization";
yield return "System.Collections.Generic";
yield return "System.Linq";
yield return "MyWebsite.Web";
yield return "MyWebsite.Models";
yield return "MyWebsite.Web.ViewModels";
yield return "MyWebsite.Web.Helpers.RazorHelpers";
}
public bool AutoIncludeModelNamespace
{
get { return true; }
}
}
Original Answer:
I don't actually know what Rioxo is and their site doesn't seem to have a download.
So I'm taking a shot here and assuming its because you haven't referenced the assembly by its name properly.
I think the name is probably Rioxo.Companion or Rioxo
So updating the <assemblies> section to something like:
<razor disableAutoIncludeModelNamespace="false">
<assemblies>
<add assembly="Server32" />
<add assembly="Rioxo" />
</assemblies>
<namespaces>
<add namespace="Rioxo.Companion.Server" />
<add namespace="Rioxo.Companion.Services" />
</namespaces>
</razor>
or
<razor disableAutoIncludeModelNamespace="false">
<assemblies>
<add assembly="Server32" />
<add assembly="Rioxo.Companion" />
</assemblies>
<namespaces>
<add namespace="Rioxo.Companion.Server" />
<add namespace="Rioxo.Companion.Services" />
</namespaces>
</razor>
Should fix the issue.
Related
We have the following value inside app.config for an asp.net console application:-
<add key="ConnectionString" value="Server=10.***\\engine;Database=ServiceDesk;Trusted_Connection=True;User ID=ad-***\\*****db.user;Password=***" />
where i have added \\ inside the key value.. now i am using this code to get the value :-
public static string tokenGet(string key)
{
NameValueCollection settings = System.Configuration.ConfigurationManager.GetSection("customAppSettingsGroup/customAppSettings")
as System.Collections.Specialized.NameValueCollection;
if (settings != null)
{
return settings[key];
}
return String.Empty;
}
but the code will return this value where it will add additional \\.. any advice how i can fix this ?
<add key="ConnectionString" value="Server=10.***\\\\engine;Database=ServiceDesk;Trusted_Connection=True;User ID=ad-***\\\\*****db.user;Password=***" />
OK, change it.
<connectionStrings>
<add name="ConnectionString" connectionString="Server=10.***\\engine;Database=ServiceDesk;Trusted_Connection=True;User ID=ad-***\\*****db.user;Password=***" />
</connectionStrings>
var connection = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString.Replace("\\","");
I want my app.config file to be something like
<configSections>
<section name ="RegCompany" type =""/>
</configSections>
<RegCompany>
<Company name="Tata Motors" code="Tata"/>
<SomethingElse url="someuri"/>
</RegCompany>
Any idea how to do this? I want to get the values defined here through my code.
For simple values like this, there is an easier solution than the one in the duplicate questions.
Config:
<configSections>
<section name="RegCompany" type="System.Configuration.NameValueSectionHandler"/>
</configSections>
<RegCompany>
<add key="CompanyName" value="Tata Motors" />
<add key="CompanyCode" value="Tata" />
<add key="CompanyUrl" value="example.com" />
</RegCompany>
Code:
var section = ConfigurationManager.GetSection("RegCompany") as NameValueCollection;
if (section == null) {
throw new InvalidOperationException("Unknown company");
}
var company = section["CompanyName"];
var code = section["CompanyCode"];
var url = section["CompanyUrl"];
I have created a custom trace listener for the EnterpriseLibrary logging block, but the Formatter property is always null.
This is the code:
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
using System;
using System.Diagnostics;
namespace test {
[ConfigurationElementType(typeof(CustomTraceListenerData))]
public class TestTraceListener : CustomTraceListener {
public override void Write(string message) {
Console.Write(message);
}
public override void WriteLine(string message) {
Console.WriteLine(message);
}
public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data) {
LogEntry entry = data as LogEntry;
if (entry != null) {
if (Formatter != null) {
string formatted = Formatter.Format(entry);
WriteLine(formatted);
} else {
WriteLine(entry.Message);
}
} else {
base.TraceData(eventCache, source, eventType, id, data);
}
}
}
class Program {
static void Main(string[] args) {
Logger.SetLogWriter(new LogWriterFactory().Create());
LogEntry entry = new LogEntry("This is a test", "General", 0, 0, TraceEventType.Information, null, null);
Logger.Write(entry);
}
}
}
And this is the configuration file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="loggingConfiguration"
type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
requirePermission="true" />
</configSections>
<loggingConfiguration name="logging" tracingEnabled="true" defaultCategory="General">
<listeners>
<add name="Console Trace Listener"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.SystemDiagnosticsTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
formatter="Simple Formatter"
type="test.TestTraceListener, test"
traceOutputOptions="DateTime, Timestamp, ThreadId" />
</listeners>
<formatters>
<add name="Simple Formatter"
type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
template="{timestamp(local:dd/MM/yy HH:mm:ss.fff)} [{severity}]: {message}" />
</formatters>
<categorySources>
<add switchValue="Information" name="General">
<listeners>
<add name="Console Trace Listener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All" name="All Events" />
<notProcessed switchValue="All" name="Unprocessed Category" />
<errors switchValue="Warning" name="Logging Errors & Warnings" />
</specialSources>
</loggingConfiguration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
</startup>
</configuration>
If I understood correctly, my listener should have the "Simple Formatter" formatter that I declared in the configuration file in its Formatter property, but this is not the case.
What am I missing?
I solved the problem with the Enterprise Library Configuration Tool (I could make it work for VS 2015 following the instructions here: Does Enterprise Library 6 work with Visual Studio 2013 and/or 2015?).
The problem was a wrong value of the listenerDataType attribute, the XML declaration of the listener should have been the following:
<add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
type="test.TestTraceListener, test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="Console Trace Listener"
formatter="Simple Formatter" />
I've below XML in my web.config
<handlers>
<remove name="ChartImageHandler" />
<add name="PageNotFoundhandelarrtf" path="*.rtf" verb="*"
modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\
aspnet_isapi.dll" resourceType="Unspecified" preCondition=
"classicMode,runtimeVersionv2.0,bitness32" />
<add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="Keyoti_SearchEngine_Web_CallBackHandler_ashx" verb="*" preCondition="integratedMode" path="Keyoti.SearchEngine.Web.CallBackHandler.ashx" type="Keyoti.SearchEngine.Web.CallBackHandler, Keyoti2.SearchEngine.Web, Version=2012.5.12.706, Culture=neutral, PublicKeyToken=58d9fd2e9ec4dc0e" />
<add path="Reserved.ReportViewerWebControl.axd"
verb="*" type="Microsoft.Reporting.WebForms.HttpHandler,
Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken
=b03f5f7f11d50a3a" validate="false" />
</handlers>
And i need to remove last node from this XML for ReportViewer in <handler> section. I first need to find <handler> section than above node should be removed.
I'm using below code but its not working...can you please guide me what's wrong with the below piece of code..
XElement xEmp = XElement.Load(PATH + WEB_CONFIG_PATH);
var empDetails = from emps in xEmp.Elements("handlers")
where emps.Element("path").Equals("Reserved.ReportViewerWebControl.axd")
select emps;
empDetails.First().Remove();
xEmp.Save(#"D:\Employees.xml");
Try to use next code snippet
XElement xEmp = XElement.Load(PATH + WEB_CONFIG_PATH);
var pathToRemove = "Reserved.ReportViewerWebControl.axd";
var empDetails= xEmp.XPathSelectElements("//handlers")
.Descendants()
.First(d => d.Attributes().Any(atr => atr.Name == "path" && atr.Value == pathToRemove));
empDetails.Remove();
xEmp.Save(#"D:\Employees.xml");
If you want to stick with query syntax, you still have to mix it a little bit:
var empDetails = from emps in xEmp.XPathSelectElements("//handlers").Descendants()
where emps.Attributes().Any(atr => atr.Name == "path" && atr.Value == pathToRemove)
select emps;
Deleting the node from XML file is given here: http://www.wrangle.in/topic/asw0zgftjzqr/C-Sharp-tricks-deleting-node-from-xml-fi
I ran this code an it seems to work. Here's what I did . . .
XDocument doc = XDocument.Parse(INPUT_DATA);
XElement handlers = doc.Element("handlers");
IEnumerable<XElement> add = null;
IEnumerable<XElement> pFind = null;
if (handlers != null)
{
add = handlers.Elements();
if (add != null)
{
pFind = (from itm in add
where itm.Attribute("path") != null
&& itm.Attribute("path").Value != null
&& itm.Attribute("path").Value == "Reserved.ReportViewerWebControl.axd"
select itm);
if(pFind != null)
pFind.FirstOrDefault().Remove();
}
}
here is the full tested code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace XDocu
{
class Program
{
static void Main(string[] args)
{
XDocument doc = XDocument.Parse(INPUT_DATA);
XElement handlers = doc.Element("handlers");
IEnumerable<XElement> add = null;
IEnumerable<XElement> pFind = null;
int oldCount = doc.Element("handlers").Elements().Count();
if (handlers != null)
{
add = handlers.Elements();
if (add != null)
{
pFind = (from itm in add
where itm.Attribute("path") != null
&& itm.Attribute("path").Value != null
&& itm.Attribute("path").Value == "Reserved.ReportViewerWebControl.axd"
select itm);
if(pFind != null)
pFind.LastOrDefault().Remove();
}
}
//print it
if (add != null)
Console.WriteLine("Old Count: {0}\nNew Count: {1}", oldCount, add.Count());
}
const string INPUT_DATA =
#"<?xml version=""1.0""?>
<handlers>
<remove name=""ChartImageHandler"" />
<add name=""PageNotFoundhandelarrtf"" path=""*.rtf"" verb=""*""
modules=""IsapiModule"" scriptProcessor=""%windir%\Microsoft.NET\Framework\v2.0.50727\
aspnet_isapi.dll"" resourceType=""Unspecified"" preCondition=
""classicMode,runtimeVersionv2.0,bitness32"" />
<add name=""ChartImageHandler"" preCondition=""integratedMode"" verb=""GET,HEAD"" path=""ChartImg.axd"" type=""System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"" />
<add name=""Keyoti_SearchEngine_Web_CallBackHandler_ashx"" verb=""*"" preCondition=""integratedMode"" path=""Keyoti.SearchEngine.Web.CallBackHandler.ashx"" type=""Keyoti.SearchEngine.Web.CallBackHandler, Keyoti2.SearchEngine.Web, Version=2012.5.12.706, Culture=neutral, PublicKeyToken=58d9fd2e9ec4dc0e"" />
<add path=""Reserved.ReportViewerWebControl.axd""
verb=""*"" type=""Microsoft.Reporting.WebForms.HttpHandler,
Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken
=b03f5f7f11d50a3a"" validate=""false"" />
</handlers>";
}
}
Compiler shows output that removes the item based on your critera correctly, we are left with . . .
<handlers>
<remove name="ChartImageHandler" />
<add name="PageNotFoundhandelarrtf" path="*.rtf" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\ aspnet_isapi.dll" resourceType="Unspecified" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
<add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="Keyoti_SearchEngine_Web_CallBackHandler_ashx" verb="*" preCondition="integratedMode" path="Keyoti.SearchEngine.Web.CallBackHandler.ashx" type="Keyoti.SearchEngine.Web.CallBackHandler, Keyoti2.SearchEngine.Web, Version=2012.5.12.706, Culture=neutral, PublicKeyToken=58d9fd2e9ec4dc0e" />
</handlers>
That is, with the exclusion of <Add path="Reserved.ReportViewerWebControl.axd" . . . />
As the title implies how can I create a new log file each day in C#? Now the program may not necessarily run all day and night but only get invoked during business hours. So I need to do two things.
How can I create a new log file each day? The log file will be have the name in a format like MMDDYYYY.txt
How can I create it just after midnight in case it is running into all hours of the night?
Update 2018: I prefer to use NLog now
Previous answer about log4net:
This example shows how to configure the RollingFileAppender to roll log files on a date period. This example will roll the log file every minute! To change the rolling period adjust the DatePattern value. For example, a date pattern of "yyyyMMdd" will roll every day.
See System.Globalization.DateTimeFormatInfo for a list of available patterns.
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\temp\rolling.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd-HHmm" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
I'd recommend something like this:
string logFile = DateTime.Now.ToString("yyyyMMdd") + ".txt";
if (!System.IO.File.Exists(logFile))
{
System.IO.File.Create(logFile);
}
//append to logFile here...
Is there a reason you want something to create it after midnight? Why not just create it if it doesn't exist when you go to log the error?
Also noticed that I changed the date format. This will allow you to sort files by name and get them in order. I always use this format when messing with dates in any way.
Others have mentioned Log4Net, so I'll go ahead and pimp the Enterprise Library Logging Block, which is also quite capable of doing what you want.
Could you please include some code that shows how easy it would be to make this roll every day? Is it easier than the log4Net example? – Daniel Dyson
Sure. Typically, one would use Enterprise Library Configuration Tool to build the configuration; this tool takes a little getting used to, but once you understand how it works, it's pretty powerful. That said, you can also edit the app.config by hand.
Here is the output of the tool I mentioned, which dumps pretty much everything into a rolling flat file that rolls every day (or if it exceeds 2MB). The formatting is the default provided by the tool.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="Category">
<listeners>
<add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
formatter="Text Formatter" rollInterval="Day" rollSizeKB="2000" />
</listeners>
<formatters>
<add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
template="Timestamp: {timestamp}{newline}
Message: {message}{newline}
Category: {category}{newline}
Priority: {priority}{newline}
EventId: {eventid}{newline}
Severity: {severity}{newline}
Title:{title}{newline}
Machine: {localMachine}{newline}
App Domain: {localAppDomain}{newline}
ProcessId: {localProcessId}{newline}
Process Name: {localProcessName}{newline}
Thread Name: {threadName}{newline}
Win32 ThreadId:{win32ThreadId}{newline}
Extended Properties: {dictionary({key} - {value}{newline})}"
name="Text Formatter" />
</formatters>
<categorySources>
<add switchValue="All" name="Category">
<listeners>
<add name="Rolling Flat File Trace Listener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All" name="All Events">
<listeners>
<add name="Rolling Flat File Trace Listener" />
</listeners>
</allEvents>
<notProcessed switchValue="All" name="Unprocessed Category">
<listeners>
<add name="Rolling Flat File Trace Listener" />
</listeners>
</notProcessed>
<errors switchValue="All" name="Logging Errors & Warnings">
<listeners>
<add name="Rolling Flat File Trace Listener" />
</listeners>
</errors>
</specialSources>
</loggingConfiguration>
</configuration>
Try out NLog (nlog-project.org). It is very flexible and easier to work with than Log4Net in my opinion.
Example NLog.config:
<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="file" xsi:type="File"
layout="${longdate} ${logger} ${message}"
fileName="${basedir}/${shortdate}/${windows-identity:domain=false}.${level}.log" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="file" />
</rules>
</nlog>
For more examples (including other logging targets besides File) see NLog configuration examples on Github
You don't need to create it at a particular time- in the simplest case you can just check if there is a logfile with today's date as it's name when you start the logging service for the app and if there isn't you can create one before you start appending to it.
The only case you need to be particularly aware of with this setup is when the application runs past midnight.
use log4net. This is one of the most commonly used library for logging.
It can be easily configured as you like, please refer to samples.
Below is the appender XML that I am currently using.
Based on your requirements of
1) creating a log file for once a day and,
2) to have the extension of txt,
you should use an XML similar to what is below.
The XML below will create a log file called system-20121106.txt.
The only issue is that since file value is logs/system- your file while it is writing for current day will be system-. To get around this, you'd have to set your file value to logs/system.txt, but then you'd get system.txt.20121106.txt as the final file.
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs/system-" />
<appendToFile value="true"/>
<countDirection value="-1"/>
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd'.txt'" />
<maxSizeRollBackups value="0" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
When you log something, check to see if a file with the current date exists, if not - create it. Simple as that :)
if(fileExists(todaysDate + ".txt")){
appendToLogFile(message);
}else{
createFile(todaysDate + ".txt");
appendToLogFile(message);
}
There is no need to create it until you need it, use:
file = new StreamWriter(path, true, new UTF8Encoding(false));
(or maybe a different encoding.) This will create the file is it does not exist, or start to append to it.
Then it is a matter of creating the filename, and just using that.
If you only need a simple TraceListener, I have a mini implementation here: https://github.com/datvm/DailyTraceListener
The output is also in CSV format so you can read it with Excel or any CSV reader.
Source code for the TraceListener:
public class DailyTraceListener : TraceListener
{
public bool UseUtcTime { get; private set; }
public string LogFolder { get; private set; }
public bool Disposed { get; private set; }
public bool HasHeader { get; private set; }
public string CurrentLogFilePath { get; private set; }
protected DateTime? CurrentLogDate { get; set; }
protected FileStream LogFileStream { get; set; }
protected StreamWriter LogFileWriter { get; set; }
private SemaphoreSlim LogLocker { get; set; } = new SemaphoreSlim(1, 1);
public DailyTraceListener(string logFolder)
{
this.LogFolder = logFolder;
}
public DailyTraceListener UseUtc()
{
this.UseUtcTime = true;
return this;
}
public DailyTraceListener UseHeader()
{
this.HasHeader = true;
return this;
}
protected virtual void WriteHeader()
{
this.LogFileWriter.WriteLine(string.Format("{0},{1},{2},{3},{4}",
"Time",
"Type",
"Source",
"ID",
"Message"));
}
protected virtual string FormatTime(DateTime time)
{
return time.ToString("o");
}
private DateTime GetCurrentTime()
{
if (this.UseUtcTime)
{
return DateTime.UtcNow;
}
else
{
return DateTime.Now;
}
}
private void InitializeLogFile()
{
this.CheckDisposed();
try
{
if (this.LogFileWriter != null)
{
this.LogFileWriter.Dispose();
}
if (this.LogFileStream != null)
{
this.LogFileWriter.Dispose();
}
}
catch (Exception ex)
{
Trace.TraceError(ex.ToString());
}
var currentTime = this.GetCurrentTime();
var fileName = $"{currentTime.ToString("yyyy-MM-dd")}.log";
this.CurrentLogFilePath = Path.Combine(this.LogFolder, fileName);
// Ensure the folder is there
Directory.CreateDirectory(this.LogFolder);
// Create/Open log file
this.LogFileStream = new FileStream(this.CurrentLogFilePath, FileMode.Append);
this.LogFileWriter = new StreamWriter(this.LogFileStream);
// Write Header if needed
if (this.LogFileStream.Length == 0 && this.HasHeader)
{
this.WriteHeader();
}
}
private void CheckFile()
{
this.CheckDisposed();
var currentTime = this.GetCurrentTime();
if (this.CurrentLogDate == null || currentTime.Date != this.CurrentLogDate)
{
this.InitializeLogFile();
this.CurrentLogDate = currentTime.Date;
}
}
private void CheckDisposed()
{
if (this.Disposed)
{
throw new InvalidOperationException("The Trace Listener is Disposed.");
}
}
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
{
var time = this.FormatTime(this.GetCurrentTime());
this.WriteLine(string.Format("{0},{1},{2},{3},{4}",
time,
eventType,
EscapeCsv(source),
id.ToString(),
EscapeCsv(message)));
}
public override void Write(string message)
{
try
{
this.LogLocker.Wait();
this.CheckDisposed();
this.CheckFile();
var currentTime = this.GetCurrentTime();
this.LogFileWriter.Write(message);
this.LogFileWriter.Flush();
}
catch (Exception ex)
{
Trace.TraceError(ex.ToString());
}
finally
{
this.LogLocker.Release();
}
}
public override void WriteLine(string message)
{
this.Write(message + Environment.NewLine);
}
protected string EscapeCsv(string input)
{
for (int i = 0; i < input.Length; i++)
{
if (input[i] == ',' || input[i] == '\n')
{
input = input.Replace("\"", "\"\"");
return $"\"{input}\"";
}
}
return input;
}
protected override void Dispose(bool disposing)
{
this.Disposed = true;
try
{
this.LogFileWriter?.Dispose();
this.LogFileStream?.Dispose();
this.LogLocker.Dispose();
}
catch (Exception ex)
{
Trace.TraceError(ex.ToString());
}
base.Dispose(disposing);
}
}