I am using the FileSystemWatcher to notify when the new files gets created in the network directory. We process the text files(about 5KB size) and delete them immediately when the new file gets created in the directory. If the FileSystemWatcher windows service stops for some reason we have to look for the unprocessed files after it gets back up and running. How can I handle if the new file comes while processing the old files from the directory? Any examples please?
Thank you,
Here is the code example I have with simple form.
public partial class Form1 : Form
{
private System.IO.FileSystemWatcher watcher;
string tempDirectory = #"C:\test\";
public Form1()
{
InitializeComponent();
CreateWatcher();
GetUnprocessedFiles();
}
private void CreateWatcher()
{
//Create a new FileSystemWatcher.
watcher = new FileSystemWatcher();
watcher.Filter = "*.txt";
watcher.NotifyFilter = NotifyFilters.FileName;
//Subscribe to the Created event.
watcher.Created += new FileSystemEventHandler(watcher_FileCreated);
watcher.Path = #"C:\test\";
watcher.EnableRaisingEvents = true;
}
void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
//Parse text file.
FileInfo objFileInfo = new FileInfo(e.FullPath);
if (!objFileInfo.Exists) return;
ParseMessage(e.FullPath);
}
void ParseMessage(string filePath)
{
// Parse text file here
}
void GetUnprocessedFiles()
{
// Put all txt files into array.
string[] array1 = Directory.GetFiles(#"C:\test\");
foreach (string name in array1)
{
string path = string.Format("{0}{1}", tempDirectory, name)
ParseMessage(path);
}
}
}
When the process starts do the following:
first get the contents of the folder
process every file (end delete them as you already do now)
repeat until no files are in the folder (check again here, since a new file could have been placed in the folder).
start the watcher
For any of our services that use the FileSystemWatcher we always process all the files that exist in the directory first, prior to starting the watcher. After the watcher has been started we then start a timer (with a fairly long interval) to handle any files that appear in the directory without triggering the watcher (it does happen from time to time). That usually covers all the possibilities.
Related
I would like to be able to run commands on the command prompt on a windows pc from an Android phone.
I am currently doing it by a wpf app on windows which listens for files with .dev in their file name.
This method is very annoying to use on a phone as I have to type out the command in a .bat file and then copy the file to D:\Shared using an app like File Manager to transfer the file via windows share
using Microsoft.Win32;
using System.Diagnostics;
namespace Dev
{
public partial class Dev : ApplicationContext
{
class Var
{
public static string temp = Path.GetTempPath();
}
public Dev()
{
RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", true);
key.SetValue("Remote Dev", Application.ExecutablePath);
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new()
{
Path = "D:\\Shared",
/* Watch for changes in LastAccess and LastWrite times, and
the renaming of files or directories. */
NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName,
// Only watch text files.
Filter = "*.dev.*"
};
// Add event handlers.
watcher.Created += new FileSystemEventHandler(Create);
// Begin watching.
watcher.EnableRaisingEvents = true;
//This method is called when a file is created.
static void Create(object source, FileSystemEventArgs e)
{
string tempPath = Var.temp + Path.GetFileName(e.FullPath);
if (File.Exists(tempPath)) File.Delete(tempPath);
File.Move(e.FullPath, tempPath);
Thread.Sleep(1000);
Process.Start("explorer", tempPath);
}
}
}
}
I would like to create an app that can automate the process of creating the .bat file and coping it to the D:\Shared without the need of any third party app.
! Please help me in the Maui part as I am new to it.
Thanks
Why do i get an IOException (The process cannot access the file because it is being used by another process.), when i copy the same file 3 Times into Folder A?
class FileWatcher {
FileSystemWatcher fsw;
FileInfo file;
string destination = #"C:\FileMover\B\";
Random random;
public FileWatcher() {
fsw = new FileSystemWatcher();
random = new Random();
fsw.Path = #"C:\FileMover\A";
fsw.Created += fsw_Created;
fsw.EnableRaisingEvents = true;
}
void fsw_Created(object sender, FileSystemEventArgs e) {
string destinationFileName = destination + e.Name;
if (!File.Exists(destinationFileName)) {
file = new FileInfo(e.FullPath);
file.MoveTo(destinationFileName);
}
else {
file = new FileInfo(e.FullPath);
file.MoveTo(destinationFileName + random.Next());
}
file = null;
}
}
Main:
class Program {
static void Main(string[] args) {
FileWatcher watcher = new FileWatcher();
while (Console.ReadKey().Key != ConsoleKey.Q) {
}
}
}
After 2 times folder B contains 2 files (sourceFileName and sourceFileName1274968236)
When i debug the section no Exception will be thrown.
Created might be raised before the file is flushed (?) into the destination. Try using Changed and check for e.ChangeType==WatcherChangeTypes.Created.
ref: http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.created(v=vs.110).aspx
Edit:
The Changed event is raised after Created, if this is due to a race-condition, probably will help but problem may still happen.
The OnCreated event is raised as soon as a file is created. If a file
is being copied or transferred into a watched directory, the OnCreated
event will be raised immediately, followed by one or more OnChanged
events.
Found this: Wait Until File Is Completely Written
and this: Is there a way to check if a file is in use?
Using tips from #celerno and the links he shared, here is what I found to work:
public FileWatcher()
{
fsw = new FileSystemWatcher();
random = new Random();
fsw.Path = #"C:\FileMover\A";
fsw.Created += fsw_Created;
fsw.Changed += fsw_Created;
fsw.EnableRaisingEvents = true;
}
and change the fsw_Created to:
if(!IsFileLocked(fi)){
if (!File.Exists(destinationFileName))
{
fi = new FileInfo(e.FullPath);
fi.MoveTo(destinationFileName);
}
else
{
fi = new FileInfo(e.FullPath);
string fileName = destinationFileName + random.Next();
fi.MoveTo(fileName);
}
fi = null;
}
Where IsFileLocked is directly taken from the link that was mentioned by #celerno.
I dropped many many copies of the file and it never threw an exception. I'm guessing an Changed event happens right after the file gets released, otherwise, if it is locked at the time of the attempted move, the Created never gets called, so the file just sits there. It appears you need both in this situation.
I just wanted to edit in order to add that the exception seemed to only get thrown when you're copying a file of the same name over and over into the source directory. Guessing the lock on that filename just needs to be released before you can copy another with the same name.
I am running a filesystemwatcher on the "w3svc1" folder, where the iis logs are stored by default. When I go to the adress localhost or anyone of my webapp localhost/xxxxx. The filesystemwatcher does not raise events. I know that there is a delay between the request and the writting in the logs, but even after one hour there is no change event raised. But then, when I open the file with notepad++, I see the logs added. Is anyone has an explaination. This is my code:
class Program
{
static void Main(string[] args)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = #"C:\inetpub\logs\LogFiles\W3SVC1";
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.IncludeSubdirectories = true;
watcher.Filter = "*.log";
watcher.Changed += new FileSystemEventHandler(OnChangedok);
watcher.Created += new FileSystemEventHandler(OnChangedok);
watcher.EnableRaisingEvents = true;
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
private static void OnChangedok(object source, FileSystemEventArgs e)
{
Console.WriteLine(e.FullPath);
}
This is because IIS open stream and write the logs into file but didn't flush the changes Immediately. When you open the file in notepad++, it access this file which trigger the file modification event . Please refer this thread also.
By default a Script written by the machine saves the files to Local/Server Path folder, but due to network issue, both the folders are not in sync. I have witten a C# Window Service program using FileSystemWatcher, DiffEngine, System.Timers and PingService as below coding to handle this.
To monitor a local folder OnChange Event, Ping server IP whether is success/fail before Compare/Copy to Server path, When Ping Fail it will goes to logtemp folder, system timer handle this and Ping again before re-dump the logtemp files.
I do not know how to use threading for this. Where should be my system timer code when the ping fails?
protected override void OnStart(string[] args)
{ //all watcher config here//
watcher.Path = "path";
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Filter = "filename_company-Pg1_Product*";
watcher.Changed += new FileSystemEventHandler(LogFileSystemChanges);
watcher.EnableRaisingEvents = true;}
private void LogFileSystemChanges(object sender, FileSystemEventArgs e)
{
FileInfo sourcepath = new FileInfo(e.FullPath);
FileInfo destPath = new FileInfo(Path.Combine(dFile, e.Name));
FileInfo _tempPath = new FileInfo(Path.Combine(tempPath, e.Name));
if (PingService())
//PingService Bool Type....Ping Specific IP Before Compare/Copy
{
if (!destPath.Exists)
{
LogEvent(destPath + " DOES NOT EXIST!! ");
CopyFunction.CopyFile(sourcepath, destPath, true, true);
}
else
{
if (BinaryDiff(sFile, Path.Combine(dFile, e.Name)))
//DiffEngine If Source & Diff are Different is TRUE.
{
CopyFunction.CopyFile(sourcepath, destPath, true, true);
}
}
string msg = string.Format("Filename {0} are {1} now at {2} ", _
e.Name, e.ChangeType, DateTime.Now.ToString());
LogEvent(msg);
}
else
{
CopyFunction.CopyFile(sourcepath, _tempPath, true, true);
}
}
Use NServiceBus (with what they call a Saga)
Its an open source project that lets you foolproof your code against cases where the network is down.
Or are you just asking how to make a thread?
If so see MSDN on examples for creating threads
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