I am using StraemWriter to log text messages to a log file. The log file should be created if it doesn't exist, appended to if the file creation date is less than a given time or recreated if created before that time. I am using the class/code below
public static class LogIt
{
private const string LOG_FNAME = #"Logfile.log";
public static void WriteMsg(string msg)
{
bool append = true;
if (File.Exists(LOG_FNAME))
{
//DateTime delDate = DateTime.Now.AddDays(-1);
DateTime delDate = DateTime.Now.AddMinutes(-30);
DateTime fileCreatedDate = File.GetCreationTime(LOG_FNAME);
if (DateTime.Compare(fileCreatedDate, delDate) < 0)
{
Console.WriteLine("DELETE FILE");
File.Delete(LOG_FNAME);
}
}
using (StreamWriter sw = new StreamWriter(LOG_FNAME, append))
{
sw.WriteLine(msg);
}
Console.WriteLine(msg);
}
}
This class is used by a simple console app run by the Task Scheduler which runs every x minutes.
The message are written as follows:
LogIt.WriteMsg("Log this message");
The messages are logged file when the file is initially created however when the file creation date is past the delete date, the file is recreated but no subsequent messages are ever written to the file.
Any ideas on why?
For some reason the file has the initial creation date (first time a file with that path ever created) as the creation date even if it is recreated after deleting. You can check the file properties and see that the log file creation date is always the same. A work around would be to update the file creation date in code whenever you recreate the file. You can use FileInfo class for that.
#MPD No problem. Here is the implementation of the workaround I suggested. Give it a try and let me know if that works.
private const string LOG_FNAME = #"Logfile.log";
public static void WriteMsg(string msg)
{
bool deleted = false;
bool append = true;
if (File.Exists(LOG_FNAME))
{
//DateTime delDate = DateTime.Now.AddDays(-1);
DateTime delDate = DateTime.Now.AddMinutes(-30);
DateTime fileCreatedDate = File.GetCreationTime(LOG_FNAME);
if (DateTime.Compare(fileCreatedDate, delDate) < 0)
{
Console.WriteLine("DELETE FILE");
File.Delete(LOG_FNAME);
//record that file was deleted and a new one will be created
deleted = true;
}
}
using (StreamWriter sw = new StreamWriter(LOG_FNAME, append))
{
sw.WriteLine(msg);
}
if (deleted)
{
//a new file is created. Make sure the creation time is set
FileInfo fi = new FileInfo(LOG_FNAME);
fi.CreationTime = DateTime.Now;
}
Console.WriteLine(msg);
}
I guess you are running this code on Windows 2003 (or maybe XP). If so: When you create a file in some directory at time T1 and the delete it and then re-create it; surprise surprise it has T1 as creation date!
I know this just because I had the same problem on Windows 2003!
BTW I use NLog now and (IMHO) it's perfect and has everything I need.
Related
I have a strange behavior on Windows 10 Pro. I have written the following C# code, which seems to work for 2 seconds until the file (txt/pdf) changes back TO ITS ORIGINAL modification / creation time. Maybe someone can explain that to me?
static void Main(string[] args)
{
var filePath = args[0];
var dateTimeStr = args[1];
try
{
DateTime dateTime;
var isOK = DateTime.TryParse(dateTimeStr,out dateTime);
if (!isOK)
{
Console.Write(string.Format("Could not parse date <{0}>! Try format <'2019-03-12 12:14:01 AM'> Exiting...", dateTimeStr));
return;
}
var fileInfo = new FileInfo(filePath);
if (!fileInfo.Exists)
{
Console.Write(string.Format("File <{0}> does not exist! Exiting...",fileInfo.FullName));
return;
}
Console.Write("Will set date <{0}> on file <{1}>. Continue [yY]?", fileInfo.FullName, dateTimeStr);
var confirm = Console.ReadLine();
if (confirm.ToLower().Contains("y"))
{
// This does not work on the original file
File.SetLastAccessTime(fileInfo.FullName, dateTime);
File.SetCreationTime(fileInfo.FullName, dateTime);
File.SetLastWriteTime(fileInfo.FullName, dateTime);
Console.WriteLine("Changed date to <{0}> on file <{1}>.", fileInfo.FullName, File.GetLastWriteTime(fileInfo.FullName));
}
else
{
Console.WriteLine("Aborted!");
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
}
(Converting my comment to an answer:)
Use ProcMon, part of Microsoft Sysinternals, to monitor filesystem activity (and many other kinds of program activity) to see exactly why the file dates are being reset.
I'll bet your program is probably just fighting with poorly-written file/folder synchronization software, like OneDrive or DropBox or dodgy anti-virus software.
I am trying to get last 5 minutes logs for use to this below code. this code is given to all logs that created I only want to last 5 minute logs. how can I get anyone can please help me...
class Program
{
static void Main(string[] args)
{
WriteLogs.WriteLog("ConsoleLog", String.Format("{0} # {1}", "Log is Created at", DateTime.Now));
Console.WriteLine("Log is Written Successfully !!!");
Console.ReadLine();
}
}
class WriteLogs
{
public static bool WriteLog(string strFileName, string strMessage)
{
try
{
FileStream objFilestream = new FileStream(string.Format("{0}\\{1}", Path.GetTempPath(), strFileName), FileMode.Append, FileAccess.Write);
StreamWriter objStreamWriter = new StreamWriter((Stream)objFilestream);
objStreamWriter.WriteLine(strMessage);
objStreamWriter.Close();
objFilestream.Close();
return true;
}
catch (Exception ex)
{
return false;
}
}
}
Assuming you are appending to the same log file with same string format, you can just read the file line by line or all lines at once. But since you need last 5 minutes logs, those logs would always be near the end of the file. So lets just use the later approach (We can also read a file line by line in reverse, but its tricky and would require lot of code and considerations).
First you need to define a function which fetches the logs from a given date as below -
public static IEnumerable<string> GetLogs(string strFileName, DateTime dateTime)
{
var path = Path.Combine(Path.GetTempPath(), strFileName);
var logs = File.ReadAllLines(path).Where(w =>
{
var date = DateTime.Parse(w.Split("#")[1]);
return date >= dateTime;
});
return logs;
}
Call the above function as below to get last 5 minutes logs -
var logs = GetLogs("ConsoleLog", DateTime.Now.AddMinutes(-5));
Environment: I have a windows console application and I am running the exe from command line.
Below is my code:
static void Main(string[] args)
{
CreatePSTUsingRedemption(args[0], args[1]);
}
private static void CreatePSTUsingRedemption(string messageFilePath, string pstPath)
{
RDOSession pstSession = new RDOSession();
RDOPstStore store = null;
store = pstSession.LogonPstStore(pstPath, 1, "combinedPST");
//actually there is a loop here to loop through each message files.
RDOMail rdo_Mail = pstSession.GetMessageFromMsgFile(messageFilePath);
rdo_Mail.CopyTo(store.IPMRootFolder);
rdo_Mail.Save();
store.Save();
completedCount++;
Console.WriteLine("FILES_PROCESSED:" + completedCount);
pstSession.Logoff();
}
Main purpose of this code is to create a single pst file combining email message(.msg) files.
Now when I run the exe, a pst file is created in the given location and its size keeps increasing as the code runs. After all the message files are processed application exists. There is no any error. Now, when I try to load this pst file in Outlook 2013. Pst is empty and its size is also reduced to 265KB every time. I don't think any process is using this pst because I can copy and move it anywhere I want. What might be the issue? Any suggestion, please?
UPDATE 1
private static void CreatePSTUsingRedemption(XmlNodeList nodelist, string pstPath)
{
System.Diagnostics.Debugger.Launch();
RDOSession pstSession = null;
RDOPstStore store = null;
RDOFolder folder = null;
RDOMail rdo_Mail = null;
try
{
pstSession = new RDOSession();
store = pstSession.LogonPstStore(pstPath, 1, Path.GetFileNameWithoutExtension(pstPath));
var enumerator = store.IPMRootFolder.Folders.GetEnumerator(); //DELETE DEFAULT FOLDERS
while (enumerator.MoveNext())
{
var defaultFolders = enumerator.Current as RDOFolder;
defaultFolders.Delete();
}
int completedCount = 0;
folder = store.IPMRootFolder;
foreach (XmlNode node in nodelist)
{
rdo_Mail = pstSession.GetMessageFromMsgFile(node["FullPath"].InnerText);
rdo_Mail.CopyTo(folder);
rdo_Mail.Save();
store.Save();
completedCount++;
Console.WriteLine("FILES_PROCESSED:" + completedCount);
}
}
finally
{
Marshal.ReleaseComObject(rdo_Mail);
Marshal.ReleaseComObject(folder);
Marshal.ReleaseComObject(store);
}
pstSession.Logoff();
Marshal.ReleaseComObject(pstSession);
GC.Collect();
}
Above is my code for the actual loop. I am loading all the email messages file path from an xml file. I still encounter same issue as above.
This is an indication that the PST store is not fully flushed to the disk and Outlook "fixes' the PST file by resetting it.
Try to explicitly release all Redemption objects first before logging off and call GC.Collect(). If you have a loop processing multiple files, release the message on each step of the loop.
private static void CreatePSTUsingRedemption(string messageFilePath, string pstPath)
{
RDOSession pstSession;
try
{
RDOPstStore store;
RDOFolder folder;
RDOMail rdo_Mail;
pstSession = new RDOSession();
store = pstSession.LogonPstStore(pstPath, 1, "combinedPST");
//actually there is a loop here to loop through each message files.
rdo_Mail = pstSession.GetMessageFromMsgFile(messageFilePath);
folder = store.IPMRootFolder;
rdo_Mail.CopyTo(folder);
rdo_Mail.Save();
store.Save();
completedCount++;
Console.WriteLine("FILES_PROCESSED:" + completedCount);
}
finally
{
Marshal.ReleaseComObject(rdo_Mail);
Marshal.ReleaseComObject(folder);
Marshal.ReleaseComObject(store);
}
pstSession.Logoff();
Marshal.ReleaseComObject(pstSession);
GC.Collect();
}
I want to monitor a log file of our PBX for changes. I made a small program that does just that with a FileSystemWatcher.
Now it's getting strange: The FileSystemWatcher never fires the Changed-Event when I simply start the program. Despite the fact that the log file really has changed. But when I open the directory in the Windows Explorer where the log file is located, the program works as expected. But only as long as the Explorer Window stays open... what the..?
Operating System: Windows Server 2008 R2
EDIT: Sorry, here is the code:
class Program
{
static void Main(string[] args)
{
new LogFileWatcher(#"C:\PBX\Dial.log");
System.Console.Read();
}
}
public class LogFileWatcher
{
public string LogFilePath { get; private set; }
private DateTime _lastLogFileWriteTime;
public LogFileWatcher(string path)
{
LogFilePath = path;
var directoryName = Path.GetDirectoryName(LogFilePath);
var fileName = Path.GetFileName(LogFilePath);
var fsw = new FileSystemWatcher { Path = directoryName, Filter = fileName };
fsw.Changed += fsw_Changed;
fsw.EnableRaisingEvents = true;
}
private void fsw_Changed(object sender, FileSystemEventArgs e)
{
// Get and fix the last write time of the log file
var fixLastWriteTime = File.GetLastWriteTime(LogFilePath);
// Don't do anything when file didn't change since last time
if (fixLastWriteTime == _lastLogFileWriteTime) return;
Console.WriteLine("File changed on: {0} - ID:{1}", DateTime.Now.ToLongTimeString(), Guid.NewGuid());
// Save last write time of the log file
_lastLogFileWriteTime = fixLastWriteTime;
}
}
EDIT2: Maybe this is important: The log file is in use by the PBX Windows-Service! I can open it with Notepad though.
For optimization reasons, the FileStream.Flush()-Method doesn't flush metadata anymore (Vista and later Microsoft operating systems). Therefore the FileSystemWatcher gets no file notification and won't fire the Changed-Method.
http://connect.microsoft.com/VisualStudio/feedback/details/94772/filestream-flush-does-not-flush-the-file-in-the-correct-way-to-work-with-filesystemwatcher-or-native-readdirectorychangesw
I have a program that's writing to a log file called "appname_yyyyMMdd.log", where appname is the name of my app, and yyyyMMdd is the current date; a sample log file name might be "loglistener_20110615.log" . Anyway, my app creates the log file fine, and it updates it as planned. However, once the date changes, the app doesn't log anything, and it doesn't create a new file. In other words, since today is 6/15, I need it to create a file called "loglistener_20110616.log" after midnight tonight, and I need it to continue logging to that new file.
Here are code excerpts:
public static void LogInfo(string format, params object[] args)
{
lock (_logLock)
{
using (StreamWriter sw = File.AppendText(GetLogPath()))
{
sw.WriteLine(GetTimeStamp() + String.Format(format, args));
}
}
}
private static string GetLogPath()
{
string appName = "loglistener";
string today = DateTime.Today.ToString("yyyyMMdd");
string fileName = appName + "_" + today + ".log";
string fullLogPath = AppDomain.CurrentDomain.BaseDirectory + fileName;
return fullLogPath;
}
I checked this similar question, but that question describes a different scenario (with a non-applicable fix).
UPDATE - Just in case googlers land on this page, I later discovered a different cause altogether w/ this. My log is logging info from an email-listening service. The service itself had a problem where it was timing out after a half-hour. So, my problem wasn't w/ CreateText / AppendText... My problem was there was nothing to log. Very annoying, but I hope other people won't be misled by this question/answer.
You should check to make sure that the file exists first.
From the File.AppendText Documentation
Type: System.IO.StreamWriter A
StreamWriter that appends UTF-8
encoded text to an existing file.
public static void LogInfo(string format, params object[] args)
{
lock (_logLock)
{
using (StreamWriter sw = File.Exists(GetLogPath) ? File.AppendText(GetLogPath()) : File.CreateText(GetLogPath())
{
sw.WriteLine(GetTimeStamp() + String.Format(format, args));
}
}
}
Try that instead
After looking at the comments and re-reading the documentation.
File.AppendText
Should always work, regardless of file existence.