I'm programming a video player in C# (the video works fine) and what I need now is to get the libvlc logs as well as my custom logs to print them in a file.
I use NLog which handles the libvlc logs (with nVLC) and I raise an event for my custom logs, and in buth cases this function is called :
private static void tracerlogs(string erreur, VLCControl.ControleUtilisateurVLC.LogLevels LvLog)
{
string path = "logs.txt";//Sera redéfini dans l'appli
if (!File.Exists(path))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine(erreur + " " + LvLog.ToString());
sw.Close();
}
}
else
{
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine(erreur + " " + LvLog.ToString());
sw.Close();
}
}
Console.WriteLine(erreur + " " + LvLog.ToString());
}
The problem is that I'm getting at random times a System.IO.IOException telling that "the process cannot access the file because it is being used by another process". Although I do close my StreamWriter (which should normally not be useful in a using block)... This makes my app crash. Does anyone have any idea why it does this ?
I finally solved it by adding a resource : as there was a conflict between different threads trying to access this function, I wrapped this :
private static void tracerlogs(string erreur, VLCControl.ControleUtilisateurVLC.LogLevels LvLog)
{
lock (LockLog) {
string path = "logs.txt";//Sera redéfini dans l'appli
if (!File.Exists(path))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine(erreur + " " + LvLog.ToString());
sw.Close();
}
}
else
{
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine(erreur + " " + LvLog.ToString());
sw.Close();
}
}
Console.WriteLine(erreur + " " + LvLog.ToString());
}
}
And I declare a public static readonly object LockLog = new Object(); in my class. This works just fine ! Thanks to those who told me that this had to see with threading.
Related
I have an issue with a file system watcher application I am working on. It seems to run fine with a single file but not with multiple files or a folder with files inside.
in the code below, I call IsFileReady to determine if the file has completed writing before trying to copy it to the other folder. However, when a new folder is created with files inside, for some reason it's hanging and not continuing.
I think it's because multiple files are being written at the same time and my code is referencing just a single file, but I am unsure of how to correct this.
Any assistance is appreciated and thank you.
static void Init()
{
string directory = watch_path;
Program._watcher = new FileSystemWatcher(directory);
Program._watcher.Created +=
new FileSystemEventHandler(Program._watcher_Changed);
Program._watcher.EnableRaisingEvents = true;
Program._watcher.IncludeSubdirectories = true;
}
static void _watcher_Changed(object sender, FileSystemEventArgs e)
{
Console.WriteLine("CHANGED, NAME: " + e.Name);
Console.WriteLine("CHANGED, FULLPATH: " + e.FullPath);
try
{
Console.WriteLine("Checking If File Exists at copy location");
if (!File.Exists(copy_path + "\\" + e.Name))
{
Console.WriteLine("Waiting for File to complete write");
WaitForFile(e.FullPath);
Console.WriteLine("Copying file to remote folder");
File.Copy(e.FullPath, copy_path + "\\" + e.Name);
Console.WriteLine("Copy Completed writing to log");
error_handling("File Copy Completed : ", copy_path + "\\" + e.Name, e.FullPath);
}
else
{
Console.WriteLine("Copy Failed Writing to Log");
error_handling("File Copy Skipped, File exists at destination : ", copy_path + "\\" + e.Name, e.FullPath);
}
}
catch (Exception error)
{
Console.WriteLine("Copy process totally failed" + error.Message);
error_handling("File Copy Failed ", "Exception: " + error.Message, "00");
}
}
public static void WaitForFile(string filename)
{
while (!IsFileReady(filename)) { }
}
public static bool IsFileReady(string filename)
{
try
{
using (FileStream inputStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None))
return inputStream.Length > 0;
}
catch (Exception)
{
return false;
}
*Edit
When it hangs, it seems that the WaitForFile never actually finishes up. When copying a single file, it finishes no problem, but I think when there are multiple files it get stuck somehow and it will not go past the
WaitForFile(e.FullPath);
I am intentionally hooking the Created event. the use of this application is to monitor a folder that needs to be identical between multiple web servers. the sync process needs to be as fast as possible as the web servers are load balanced.
the Call to error_handling is just a write to log function as seen below:
public static void error_handling(string message, string fileident, string source)
{
using (System.IO.StreamWriter myFile = new System.IO.StreamWriter(log_folder + "\\" + log_file, true))
{
string finalMessage = string.Format("{0}: {1} SOURCE: {3} - DEST: {2}", DateTime.Now, message, fileident, source, Environment.NewLine);
myFile.WriteLine(finalMessage);
myFile.Close();
}
}
I have tried to write a string on text file,but its not writing anything and there is no exceptions. My code is:
public void CreateLog(string sLogInfo)
{
string sDestionation = null;
string sFileName = DateTime.Now.ToString("yyyyMMdd") + "_log.txt";
sDestionation = #"D:\Log\";
//sDestionation = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + ConfigurationManager.AppSettings["DestinationPath"].ToString();
string sFile = sDestionation + sFileName;
if (!System.IO.Directory.Exists(sDestionation))
{
System.IO.Directory.CreateDirectory(sDestionation);
}
StreamWriter oWriter = null;
if (!System.IO.File.Exists(sFile))
{
oWriter = File.CreateText(sFile);
}
else
{
oWriter = File.AppendText(sFile);
}
oWriter.WriteLine(DateTime.Now.ToString() + ": " + sLogInfo.Trim());
}
StreamWriter is IDisposable object. You should dispose it after using. For this you can use using statement like this:
public void CreateLog(string sLogInfo)
{
string sDestionation = null;
string sFileName = DateTime.Now.ToString("yyyyMMdd") + "_log.txt";
sDestionation = #"D:\Log\";
var sFile = sDestionation + sFileName;
if (!Directory.Exists(sDestionation))
{
Directory.CreateDirectory(sDestionation);
}
using (var oWriter = new StreamWriter(sFile, true))
oWriter.WriteLine(DateTime.Now + ": " + sLogInfo.Trim());
}
Use File.AppendAllText that will do all the steps (except creating folder) for you.
Otherwise you should properly dispose writer when you are done, preferably with using in the same function:
using(oWriter)
{
oWriter.WriteLine(DateTime.Now.ToString() + ": " + sLogInfo.Trim());
}
Your code looks fine, however, I think you should add at the end of it the following:
oWriter.Close()
You should flush (disposing is enough) your data into the file at the end of your code:
oWriter.Flush(); //Save (Clears all buffers for the current writer and causes any buffered data to be written to the underlying stream.)
oWriter.Dispose(); //Then free this resource
As Yuval mentioned looking at C#'s StreamWriter.cs class it does indeed calls the Flush method internally. See here: Reference
This code will create "output.txt" in C:\temp if it doesn't already exist. However, log.WriteLine(); doesn't work for me. When I open the file, I don't see it. Why is this?
private static string LogFile = #"C:\Temp\output.txt";
private StreamWriter log;
if (!File.Exists(#"" + LogFile))
{
log = new StreamWriter(#"" + LogFile);
}
else {
log = File.AppendText(#"" + LogFile);
}
log.WriteLine("["+DateTime.Now + "]: ");
You need to close the StreamWriter. It's best to use a using block for this, as it guarantees that the StreamWriter will be closed, even if an exception is thrown.
using (var log = GetLog()){
log.WriteLine("["+DateTime.Now + "]: ");
}
...
public StreamWriter GetLog(){
if (!File.Exists(#"" + LogFile))
{
return new StreamWriter(#"" + LogFile);
}
else {
return File.AppendText(#"" + LogFile);
}
}
Just a little improvement in code to #John Saunders answer.
using (var log = GetLog())
{
log.WriteLine("["+DateTime.Now + "]: ");
}
...
public StreamWriter GetLog()
{
return new StreamWriter(LogFile, File.Exists(LogFile));
}
The second parameter StreamWriter constructer takes determines append operation. Thus if file exists append otherwise not will do it. I think this is neater. And actually you can even do:
using (var log = new StreamWriter(LogFile, true))
{
log.WriteLine("["+DateTime.Now + "]: ");
}
Always appends, and if file does not exist creates it.
If you are always appending the same thing to the file whether or not it already exists, you don't need the conditional.
File.AppendText will create the file if it doesn't exist.
private static string LogFile = #"C:\Temp\output.txt";
using (StreamWriter sw = File.AppendText(LogFile))
{
sw.WriteLine("["+DateTime.Now + "]: ");
}
As John Saunders already said, you need to Dispose the stream writer, which will be done by putting it in a using statement.
(Documentation for StreamWriter)
Ok so heres the thing. When ever a trigger is hit i append my logs in a specific folder. The code works fine and it appends it correctly but if i try to manually delete the folder from the desktop its giving a "The action cannot be completed cause the folder/file is open in another program";
i guess im not disposing it right but i dont know where i missed it. I know its the folder that is attached to the process cause i tried to delete the .log file inside and it allowed me.
private void LogEvent(string filename,bool AppendTxt,string msg)
{
string sLogFormat = DateTime.Now.ToShortDateString().ToString() + " " + DateTime.Now.ToLongTimeString().ToString() + " ==> ";
msg = sLogFormat + msg;
// create directory
if (System.IO.Directory.Exists("C:\\Users\\DT-Npax\\Desktop\\LOGS1") != true)
{
Directory.CreateDirectory("C:\\Users\\DT-Npax\\Desktop\\LOGS1");
}
string dailyLog = "C:\\Users\\DT-Npax\\Desktop\\LOGS1" + "\\" + filename + ".log";
FileStream FS = null;
//write or append txt
if (!AppendTxt)
{
if (File.Exists(dailyLog))
{
File.Delete(dailyLog);
}
using (FS = File.Create(dailyLog)) { }
FS.Close();
StreamWriter TXT_WRITE = new StreamWriter(dailyLog);
TXT_WRITE.WriteLine(msg);
TXT_WRITE.Close();
}
else
{
if (!File.Exists(dailyLog))
{
using (FS = File.Create(dailyLog)) { }
FS.Close();
}
FileStream FSAppend = new FileStream(dailyLog, FileMode.Append, FileAccess.Write);
StreamWriter TXT_WRITE = new StreamWriter(FSAppend);
TXT_WRITE.WriteLine(msg);
TXT_WRITE.Close();
FSAppend.Close();
}
}
Your code does seem to close the file properly but not in an exception-safe manner.
You also have some unnecessary code in there (like using (FS = File.Create(dailyLog)) { } FS.Close(); ).
The smallest modification looks like this:
else
{
//if (!File.Exists(dailyLog))
//{
// using (FS = File.Create(dailyLog)) { }
// FS.Close();
//}
using (FileStream FSAppend = new FileStream(dailyLog, FileMode.Append, FileAccess.Write))
using (StreamWriter TXT_WRITE = new StreamWriter(FSAppend))
{
TXT_WRITE.WriteLine(msg);
}
//TXT_WRITE.Close();
//FSAppend.Close();
}
But I would rewrite this whole method like:
private void LogEvent(string filename,bool AppendTxt,string msg)
{
string sLogFormat = DateTime.Now.ToShortDateString().ToString() + " "
+ DateTime.Now.ToLongTimeString().ToString() + " ==> ";
msg = sLogFormat + msg;
// create directory
if (System.IO.Directory.Exists("C:\\Users\\DT-Npax\\Desktop\\LOGS1") != true)
{
Directory.CreateDirectory("C:\\Users\\DT-Npax\\Desktop\\LOGS1");
}
string dailyLog = "C:\\Users\\DT-Npax\\Desktop\\LOGS1" + "\\" + filename + ".log";
if (AppendText)
System.IO.File.AppendAllText(dailylog, msg);
else
System.IO.File.WriteAllText(dailylog, msg);
}
There is no need to pre-create or delete files.
Wrap the streams in a using block since they implement IDisposable.
I must say this code is a little odd...
using (FS = File.Create(dailyLog)) { }
FS.Close();
StreamWriter TXT_WRITE = new StreamWriter(dailyLog);
TXT_WRITE.WriteLine(msg);
TXT_WRITE.Close();
Shouldn't it be something like:
using (FileStream FS = File.Create(dailyLog))
{
using(StreamWriter TXT_WRITE = new StreamWriter(dailyLog))
{
TXT_WRITE.WriteLine(msg);
}
}
This is main program.cs
LogError.WriteError("Application started: " + DateTime.Now + Environment.NewLine);
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new CrawlerApp());
}
catch (Exception e)
{
LogError.WriteError(e);
}
LogError.WriteError("Application closed: " + DateTime.Now + Environment.NewLine);
and this is LogError class
public static class LogError
{
public static void WriteError(Exception e)
{
WriteError("Message: " + e.Message + Environment.NewLine + "Stack trace: " + e.StackTrace);
}
public static void WriteError(string error)
{
try
{
StreamWriter sw = File.AppendText("log.txt");
sw.WriteLine(DateTime.Now + Environment.NewLine);
sw.WriteLine(error + Environment.NewLine);
sw.WriteLine(Environment.NewLine);
sw.Close();
}
catch (Exception)
{
//
}
}
}
When i publish application and run it log.txt file is never created. If i run application from bin/debug folder then works. Why when i publish app logging not working. I am using win 2003 OS.
It could be an UnauthorizedAccessException.
Rather than guess at it you might want to change your catch to log to the event log rather than just swallowing it
File.AppendText only works if the file already exists: http://msdn.microsoft.com/en-us/library/system.io.file.appendtext.aspx. This link also has this sample code:
string path = #"c:\temp\MyTest.txt";
// This text is added only once to the file.
if (!File.Exists(path))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine("Hello");
sw.WriteLine("And");
sw.WriteLine("Welcome");
}
}
// This text is always added, making the file longer over time
// if it is not deleted.
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine("This");
sw.WriteLine("is Extra");
sw.WriteLine("Text");
}
you could use this code too, it works whether the file exits or not. As a plus it creates the log file based on the current DateTime in YYYYMMDD format
private static void doLog(String message)
{
//getting current date
String dateStr = "";
int day, month, year;
year = System.DateTime.Now.Year;
month = System.DateTime.Now.Month;
day = System.DateTime.Now.Day;
dateStr += year.ToString() + "";
if (month < 10) dateStr += "0";
dateStr += month.ToString() + "";
if (day < 10) dateStr += "0";
dateStr += day.ToString() + "";
//writting the message
string logFile = Environment.CurrentDirectory + #"/LOG_" + dateStr + #".txt";
System.IO.StreamWriter sw = new System.IO.StreamWriter(logFile, true);
sw.WriteLine(System.DateTime.Now.ToString() + "\t" + message);
sw.Close();
}
Your log-writing code is probably throwing an exception. Try removing the try/catch in WriteError to see what exception is being thrown.