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.
Related
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 want to detect and log to file Explorer operations such as copy/cut/delete/paste.
I have read about FileSystemWatcher, but I also noticed it has some issues since there is no copy/cut events available which can be confusing with whatever I want to do.
The operating system and FileSystemWatcher object interpret a cut-and-paste action or a move action as a rename action for a folder and its contents. If you cut and paste a folder with files into a folder being watched, the FileSystemWatcher object reports only the folder as new, but not its contents because they are essentially only renamed.
FileSystemWatcher is hooking the create file and delete file events to the changed and renamed events which can't really help me to determine if it was made by the user or some another process. Furthermore I cannot be 100% sure what happened to the file whether it was copied or cut etc.
I also need to keep track of the locations "from/to" and the name of file.
Is there some alternative to the FileSystemWatcher that can distinguish between these actions?
I think the FileSystemWatcher would be of use in this scenario. You could use the Changed event, which occurs when a file or directory is changed - like a copy/paste action.
See the MSDN Documentation for this event, and the class itself. Note that there are other events that you can also use for the delete/cut actions.
The events use the FileSystemEventArgs which contains properties for FullPath and Name.
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.
I have some code that watches the file system for changes and updates a container of file representations. All works for the most part, until you rename a directory. I would expect to get a rename event for all the files and subfolders of the renamed directory since they have new paths, but I only get a single message that the parent directory has changed names. Is there an event i've forgotten, or a flag that needs set? Currently I'm handling the directory rename and iterating through my collection to update the files to the new name, but I feel like there should be something in place to receive a notification for each file instead.
My setup:
FileSystemWatcher watcher = new FileSystemWatcher(item.Path);
watcher.EnableRaisingEvents = true;
watcher.Created += new System.IO.FileSystemEventHandler(OnMediaCreated);
watcher.Deleted += new System.IO.FileSystemEventHandler(OnMediaDeleted);
watcher.Changed += new System.IO.FileSystemEventHandler(OnMediaChanged);
watcher.Renamed += new System.IO.RenamedEventHandler(OnMediaRenamed);
I don't think one usually consider the contained files to be changing if the container changes it's name. Which would be why you don't get an event for the contained files.
May I suggest that you create a double-linked tree-representation of the directory structure, so that each file and directory knows of the container it is in. Then make a ToString() override in the file representation that traverses your tree to the root to build the display-string.
When you get your directory rename event you can find the directory in your representation and trigger an update for each of the files leafing out from this branch.
That way you won't have to loop through things, but rather use recursion, if that seems more elegant to you.
Also, note that FileSystemWatcher has a buffer overflow issue you might wanna check out so you don't loose events.
Ok, for a start, please use consistent terminology within the post. You've mentioned directory, folder, and file almost interchangeably. For the sake of discussion I'll drop this down to folders and files. From what you describe you are watching a folder which contains files and possibly sub-folders. You rename the folder, and you are expecting media renamed events for all of the files (and sub-folders if applicable) to be raised as well? No, I don't believe you will get them.
The FileSystemWatcher hooks in to watch the contents of a folder, not the folder itself. You can verify this behaviour by hooking to a folder and renaming the folder then renaming an item within the folder. (and displaying the full path of the change) you will notice that the path of the renamed item retains the original folder name. Renaming the folder does not invalidate the watcher, but it doesn't catch the event either. However, if you have a sub-folder under the watched folder, with a file under it, and rename the sub-folder and it's child file, the full path of the child will reflect it's parent folder's name change. Kind of hard to describe but: (IncludeSubdirectories = true)
Folder1 (watched)
File1
Folder2
File2
Renaming Folder 1 then file 1. Folder1's name change is not detected, and no, file 1 won't fire a change either. It's name didn't change. Renaming File1 after Folder1's name change will still show "Folder1" as the path.
Renaming Folder2 will be detected and report back the new name. renaming File2 after Folder2 was renamed will be detected and File2's full path will show the updated Folder2 folder name.
If you want to detect renames to the watched directory then what you actually need to do is watch the directory level above it with a Filter set to the directory you're actually interested in. Either use one FSW with IncludeSubdirectories, or two filesystem watcher, one watching the folder, and another for it's contents. When the folder change is detected, update your external references with the folder name change as necessary, then re-initialize the content watcher one so that path names are returned correctly.
You need to enable your FileSystemWatcher object to Include subdirectories.
watcher.IncludeSubdirectories = true;
FileSystemWatcher C#
Folder Structure C:\A\B\C\D\E\F\abc.txt
Delete a nested folder B fires only one event for the root folder B
But Shift + Delete fires the events for all sub folders and files.
I need to get Delete nested folder events same as Shift + Delete
The below question is similar to my requirement, but it's not working
C# FileSystemWatcher.Deleted not Firing on "normal" deleting?
The below question is similar to my requirement, but it's not working
Define "not working". As mentioned in the accepted answer for question that you referenced, the default behavior in Windows is that when you press the delete key, the file is not actually deleted- it is moved to a special folder called the recycle bin.
If you handle the renamed and changed events, you should see evidence of the moves to the recycle bin, but as you found the events will probably be raised only for the parent folder (see also Detecting moved files using FileSystemWatcher). There is probably no way to get the events for the child folders/files. If you need to keep track of the children, you'll need to index them into some data structure before they get deleted.
Also, keep in mind that some people (like me) disable the recycle bin altogether, and for us a delete is a delete.