Hi @水 知 ,
Thanks for reaching out.
The sample code below is just for reference, so you would likely need to adjust it a bit to fit your app structure, lifecycle, permissions, and the specific folders or libraries your project is working with.
If you need this to stay reasonably reliable even when the app is not running, I probably would not rely on FileSystemWatcher alone. It can still work well for live updates while your process is active, but it only works while the app is running, and it may miss events if the internal buffer overflows during heavier file activity.
For WinUI 3, a better fit may be the Windows file change tracking API, mainly StorageLibraryChangeTracker together with StorageLibraryChangeReader. That API is intended for tracking file adds, deletes, modifications, renames, and moves over time, including changes that happen while the app is closed.
This generally works best if the location you are watching is a user library such as Documents, Pictures, or Videos, or another supported local or removable folder. It usually would not be the right choice for network or NAS paths.
The suitable flow is to enable change tracking first:
using Windows.Storage;
StorageLibrary videosLib = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
StorageLibraryChangeTracker tracker = videosLib.ChangeTracker;
tracker.Enable();
Then when your app starts, resumes, or gets activated to process changes, enable it again before reading and pull the pending batch:
StorageLibrary videosLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
// Enable again before enumeration to avoid race conditions.
videosLibrary.ChangeTracker.Enable();
StorageLibraryChangeReader changeReader = videosLibrary.ChangeTracker.GetChangeReader();
var changeSet = await changeReader.ReadBatchAsync();
foreach (StorageLibraryChange change in changeSet)
{
if (change.ChangeType == StorageLibraryChangeType.ChangeTrackingLost)
{
videosLibrary.ChangeTracker.Reset();
// Re-enumerate and rebuild your index here.
return;
}
// Handle add, delete, modify, rename, or move here.
}
await changeReader.AcceptChangesAsync();
Calling AcceptChangesAsync() is important because without it, the same batch would normally be returned again next time. If more changes happen after ReadBatchAsync() but before AcceptChangesAsync(), those newer ones should stay available for the next read.
If you want the app to wake up when changes happen even while it is not open, you could also look at registering a background task with StorageLibraryChangedTrigger. That can give you a way to process the tracked changes outside a normal foreground session.
There are a couple of practical details to keep in mind. The tracker uses a circular buffer, so if a very large number of operations happen before your app reads them, you may get ChangeTrackingLost, and the usual recovery would be to rescan the library and rebuild your cache or database. Also, adding or removing root folders from a StorageLibrary does not create change tracker entries, so if that matters in your case, you would probably want to handle it through StorageLibrary.DefinitionChanged or by rechecking StorageLibrary.Folders.
If helpful, here are the official docs that are most relevant:
- Track file system changes in the background: https://learn.microsoft.com/windows/apps/develop/files/change-tracking-filesystem
- StorageLibraryChangeTracker: https://learn.microsoft.com/uwp/api/windows.storage.storagelibrarychangetracker
- FileSystemWatcher: https://learn.microsoft.com/dotnet/api/system.io.filesystemwatcher
- File access permissions for Windows apps: https://learn.microsoft.com/windows/apps/develop/files/file-access-permissions
Hope this helps! If my explanation and the information I provided were also helpful, I would greatly appreciate it if you could follow the instructions here so others with the same problem can benefit as well.