Reputation: 1907
I have another problem with my FileSystemWatcher ;) Simply, what I want to do:
I want to watch specific folders, in order to add the paths of the files to a List(Of String) and set an integer-variable for each new file.
So:
I create the file "Test.png" and it does that:
(List) categoryFilesList.Add(e.FullPath)
(Integer-variable) counter += 1
Well, this is working well.
Now, if a file is deleted again, it should remove the path from the list and set the integer-variable down again. (-= 1).
This is working well, too, but now I have a problem, I am not able to find a solution for.
I have IncludeSubdirectories
set to true
to scan the subdirectories for files. On adding this works fine, but on removing it does not.
That is because I do NOT add folders to the list, only files. So, if I delete a folder, I am not able to know what content it was containing and how much files it were, because it is already gone.
But I would want to know, how many files there were in and what their paths were to remove them again from the list and set the integer-variable down again with the amount of deleted files.
I though about saving it anyway on changing, but I do not know how exactly and if this is a good idea. Is there a better solution?
If something is unclear, then I am sorry, ask then. I also accept C#-answers, VB.NET is just because my friend wants that.
Thanks!
Upvotes: 4
Views: 1351
Reputation: 1827
My solution to a similar problem is as follows:
Ensure your FileSystemWatcher
is configured to track subfolders. Once you do that, you should get a Delete event any time a folder or file is deleted. In the case where a folder is deleted, simply iterate through your collection and remove any items that contain the path of the folder.
For example:
int numRemoved = categoryFilesList.RemoveAll(
delegate(String s)
{
return s.Contains(<DeletedDirectoryPath>);
}
);
This would remove any items in your list which contain . You can then use numRemoved to maintain your file count. Alternatively, you could simply use the count of the list instead of maintaining your own copy of that data via the Count
property on your list.
Additionally you should be sure that you handle the cases where items and directories are renamed so that your list of filenames is always up to date.
Upvotes: 2
Reputation: 2857
I am afraid that this isn't really possible to do, because of the way the deletion of a directory works in a system. The directory is deleted, but the files recursively are just part of the directory.
This was quite well described here on MSDN forums :
I you observe the behavior of the trash on your desktop, you will see that each time you delete a folder, you can see that folder in the trash but you cannot see the elements within that dropped folder. The only way to see those elements is to recover the folder from the trash.
I think it happens the same thing with the FSW class. When you delete a folder inside a watched directory you only have the event of the deleted folder because the folder and its contents is not really deleted but only moved to the trash. This is why you never receive the deleted events for the included files because they are still somewhere on your system
According to this question here on SO, the same problem occurs when a folder is moved into the structure (and the question also shows the workaround to the moving issue).
Possible workaround for the deletion problem would be browsing the structure in advance and saving the amount of files in the directories into a tree-like structure, but it will definitely be much more complex than this. It would look like this:
public class DirectoryFiles
{
public int Count {get; set;}
public string FullPath {get; set;}
public List<DirectoryFiles> Subdirectories {get; set; }
}
private DirectoryFiles Initialize(string fullPath)
{
if (Directory.Exists(fullPath))
{
var toReturn = new DirectoryFiles { Subdirectories = new List<DirectoryFiles>() };
foreach (string directory in Directory.GetDirectories(fullPath))
{
toReturn.Subdirectories.Add(this.Initialize(directory));
}
toReturn.Count = toReturn.Subdirectories.Sum(x => x.Count) + Directory.GetFiles(fullPath).Count();
return toReturn;
}
else
{
throw new DirectoryNotFoundException(String.Format("Directory {0} does not exist", fullPath));
}
}
and in the class where you are counting:
private int GetCountOfFiles(DirectoryFiles files, string fullPath)
{
if (files.FullPath.Equals(fullPath, StringComparison.InvariantCultureIgnoreCase))
{
return files.Count;
}
foreach (var subdir in files.Subdirectories)
{
if (this.GetCountOfFiles(subdir, fullPath) != -1)
{
return subdir.Count;
}
}
return -1;
}
This may need improvements for:
DirectoryFiles Parent
to DirectoryFiles and recount the directories on the way up.Upvotes: 2