This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How can I watch a file system directory to see when files are added to it?
I am creating a console app in c# which one of its functionality is to scan a fix folder path(example c:\FixedFolderA) say every minute and check if a new folders has been created(Example c:\FixedFolderA\NewFolderB).
So several folders will be created under c:\FixedFolderA.
The new folders will have no subdirectories, just files which I will copy to other locations.
I am not sure of the most efficient design to do this and need your help.
I was thinking of this workflow:
Scan c:\FixedFolderA at the start of the program.
Store all the sub directories in a list.
Create a worker process that scans c:\FixedFolderA and check to see if that sub-directory exists in the list. If the directory doesn't exist perform some action.
My concern is that the umber of sub-directories in c:\FixedFolderA will increase overtime and the program would be traversing all these directories every minute.
Should the routine to check every minute be done with a process?
Can someone please share your ideas with the best design to get me started ?
Thanks .
If you plan to watch a folder for changes, use the FileSystemWatcher class.
Also, if this console application performs a specific task on its own, perhaps it is best to turn it into a Windows Service.
It's almost always better to be notified when an event occurs rather than having to query periodically.
For the context you're describing you can very easily use the FileSystemWatcher class to specify what kind of files you want to be notified about and in which directory you wish to monitor. I put together the following code for you:
FileSystemWatcher fileWatcher = new FileSystemWatcher("C:\\Users\\ByteBlast\\Desktop", "*.*")
{
EnableRaisingEvents = true,
IncludeSubdirectories = true,
NotifyFilter = NotifyFilters.DirectoryName
};
fileWatcher.Created += (sender, eventArgs) => Console.WriteLine("{0} Created", eventArgs.FullPath);
Where I specify the path to my desktop, you will specify for example, C:\FixedFolderA.
You can make sure that you are notified about changes in sub directories by enabling the IncludeSubDirectories property like I did above.
Because you're only interested in folders and not files I set the NotifyFilter property to NotifyFilters.DirectroyName.
Place the code above in your Console Application's void Main() and ensure you stop the console from closing by for example including the following statement beneath the code above Process.GetCurrentProcess().WaitForExit();.
Rather than scanning the directory every minute, you should take a close look at File System Watcher. This will tell you when a change has been made to the directory structure - thus it will be far more efficient. Your program just has to keep track for what changes have been made.
Related
I am using a FileSystemWatcher and i got 2 cases that don't raise events.
lets say i watch on C:/temp,
In case i have already 2 folders with files inside the watched directory, if i cut-paste or move them inside the watched dir to another folder i dont get any event.
Some one know a way i can get events on this files that moved?
Watched directory:
c:/temp
|--test1
| |--test1.txt
|
|--test2
| |--test2.txt
if i move or cut-paste test2 folder into test1 i don't get event on test2.txt.
EDIT: I'm using the code from FileSystemWatcher docs which can find here:
https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=net-5.0
hope you can help me, thanks :)
Moving a folder or a file doesn't change it. If you want to track moves, make sure to watch for the Renamed event and set the filters appropriately.
As per the documentation:
COPYING AND MOVING FOLDERS
Event Handler
Events Handled
Performs
OnChanged
Changed, Created, Deleted
Report changes in file attributes, created files, and deleted files
OnRenamed
Renamed
List the old and new paths of renamed files and folders, expanding recursively if needed.
Note that strictly speaking, the file system watcher doesn't watch for changes in content - only the filesystem entries. It's possible to change file contents without changing the filesystem entries, so make sure that it's good enough for your use.
I told my FileWatcher, that it should include Subdirectories
_watcher.IncludeSubdirectories = true;
The problem, that I have is, that there are multiple files with the same file-ending.
So my watcher gets triggered multiple times.
I have something like this
(subfolder[x] is the watched one)
mainFolder/subfolder[x]/ -> in this one example.mkv and two other filetypes
mainFolder/subfolder[x]/subfolder2/ -> in this one is just one sample.mkv
FileWatcher is configured to:
_watcher.Filter = "*.mkv";
Currently the "created" event gets triggered two times ("example.mkv" and "sample.mkv")
I would like to have it just triggered once for the "example.mkv" and not for the "sample.mkv".
How can I just "watch" the first subfolder and exclude the second subfolder?
You want to only Watch the target and 1st Order Child Directories/first two levels of the directory tree. Close to 0 code that is able to include subdirectories recusively on a Windows ever had such an ability. It was either "incldue all subdirectories" or "include no subdirectories".
Only code as modern as Robocopy has any ability to define the "depth". And FileWatcher is not nearly that modern. It is (t)rusty like hte Office COM Interop. It is still following the old "all Subdirectories or None" pattern. So you still have to use the old workaround - manual recursion:
Do not use IncludeSubdirectories = true;
Start a normal, non recursive File watcher on the root directory
Itterate over all subdirectories manually. The Directory class should have you covered
Start a seperate, non-recursive watcher for each subdirectory
Unfortuantely FileWatcher is not the most advanced class. For example figuring out wich kind of changed happened is nigh impossible. Wich is why someone took 9 watches with Filters and put them into one class, to get some decent level of information out of this class: https://www.codeproject.com/Articles/58740/FileSystemWatcher-Pure-Chaos-Part-of
I'm creating a program that scans for changes, not create or delete, in ALL the files in a given directory, and all of his sub directories, in the past 24 hours.
I've seen lots of other examples/tutorials but not all of them do what I'm looking for.
This is my code so far:
using System.IO;
public static void Main(string[] args)
{
string myDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), #"C:\Path");
var directory = new DirectoryInfo(myDirectory);
DateTime from_date = DateTime.Now.AddDays(-1);
DateTime to_date = DateTime.Now;
var files = directory.GetFiles()
.Where(file => file.LastWriteTime >= from_date && file.LastWriteTime <= to_date)
.ToArray();
Console.WriteLine();
}
The problem is that the code above only tells me the last change in the directory. What I want is a log of all the changes in the directory.
I am a learning student, so lots of explanation would be great! :)
I am NOT, I repeat NOT, looking for FileSystemWatcher, I don't want my server to stay on for 24 hours straight. I want to start this program once every 24 hours, make a log, close it.
If anyone can help me out with this, or at least give me something to start with, I would very much appreciate it!
EDIT
I finally my goal to work via another code, a whole different code.
I want to thank you all for helping me and raising up my understanding of a couple of things
Without a FileSystemWatcher you would have to have an external file which you would use to compare differences.
So on first run you would get
File 1
File 2
File 3
No changes!
Next run you might get
File 1
File 3
File 4
and you would be able to compare the first list to show that File 2 is missing and File 4 is new...
It is not possible. Neither files have log of changes nor OS writes such log. Only information you can get is a last write time. If you need whole log, then you should create it manually (e.g. create windows service with FileSystemWatcher), or you can consider to use some version control system, which tracks all changes to files (in this case changes to files should be done though version control software).
As others have already written: Without a file system watcher or storing a list of files you have no chance to detect deleted files. Also it is possible to change the file date (however, I do not know whether it is possible to change last write time or only create time). Also renaming a file usually does not change any file date.
The problem is that the code above only tells me the last change in the directory
I tested your code in VS 2010, and in the debugger I see multiple entries in the variable files. Maybe you only have one modified file in the directory itself and the other changed files in sub directories (see belov)? Maybe your output is wrong?
If you really have multiple recently changed files in the directory, I'd suggest to use an additional variable for intermediate results to check where the error occurs. (Does directory.GetFiles() give you an incomplete file list or is there a problem with the filter in where?)
Last but not least, you write
and all of his sub directories
According to MSDN GetFiles only returns the files in the current directory. If you also want sub directories, you have to recurse into them. Of course you should address the problem of incomplete file list before adding recursion.
Hope that helps
Depending on your needs, this may (as far as I know) not even be possible to do cleanly in .NET - what you're really looking for could be done using a File System Minifilter Driver, which runs in kernel space quietly and can intercept all IRP packets within a certain filepath (e.g. C:\Sub*). Such a program can be loaded using fltmc.exe command.
This question already has answers here:
C# : file copy notifying [closed]
(2 answers)
Closed 9 years ago.
I am trying to keep track of files that are copied by users and other applications.
The FileSystemWatch only has events for Changed, Created, Deleted, Disposed, Error, and Renamed.
It doesn't fire an event when a file is accessed by the copy function or where the new file is being copied to.
Is there a method for monitoring the copy event/function of windows?
I don't know of any way using C#.
You can do this if you are willing to write a File System Filter Driver. [Definitely expert territory, as there is scope for corrupting files and/or bringing down your system]
A file system filter driver intercepts requests targeted at a file
system or another file system filter driver. By intercepting the
request before it reaches its intended target, the filter driver can
extend or replace functionality provided by the original target of the
request. Examples of file system filter drivers include anti-virus
filters, backup agents, and encryption products. To develop file
systems and file system filter drivers, use the IFS (Installable File
System) Kit, which is provided with the Windows Driver Kit (WDK).
You are doing the right thing with FileSystemWatcher. Windows does not have any built-in mechanism for reporting copies reliably.
You could hook the OS copy routine, but this won't guarantee you good results: applications are free to implement their own copy by just opening the source and destination files and copying the bytes over.
Renaming is different because a rename done by the OS cannot be easily mimicked through other means, so you will catch all renames with the FileSystemWatcher. Note that moving between drives is more like copy: you won't get a Renamed notification, but a Created and a Deleted instead.
So if you really really need to notice a file getting copied, my suggested approach is this:
Hook the CloseFile calls, in addition to the FileSystemWatcher.
Whenever a file gets closed, it could be because it's the source or target of a copy / cross-drive move. Check its size.
If you find two closed files with the same size within a reasonably short period of time, compare the content. Pretty resource-intensive, but the only reliable way to do this.
You can use Auditing file and folder access feature of Windows which writes an event log entry and you can setup programs to start when such an event occurs
I can't think of any good way.
For each newly created file, you need to check if there is an exact duplicate (perhaps with a different name) anywhere on the filesystem. You could obviously do this brute-force, but the solution would be very inelegant, slow and brittle!
In c# winforms application, I want to choose a directory from network and after that, when any body put a file in it, I want to see a message such as "A file added."
for example I can get filepaths.
string[] filePaths = Directory.GetFiles(#"c:\MyDir\", "*.bmp");
should I run this code 5 minutes later and should I check the differences?
You could use the FileSystemWatcher class and subscribe for different events happening on the file system such as files and folders being created, deleted, modified, ...