Udostępnij przez


Śledzenie zmian w systemie plików w tle

ważne interfejsy API

Klasa StorageLibraryChangeTracker umożliwia aplikacjom śledzenie zmian w plikach i folderach podczas poruszania się po systemie przez użytkowników. Korzystając z klasy StorageLibraryChangeTracker, aplikacja może śledzić:

  • Operacje na plikach, w tym dodawanie, usuwanie, modyfikowanie.
  • Operacje folderów, takie jak zmienianie nazw i usuwanie.
  • Pliki i foldery przenoszone na dysku.

Skorzystaj z tego przewodnika, aby poznać model programowania do pracy z monitorem zmian, wyświetlić przykładowy kod i zrozumieć różne typy operacji na plikach śledzonych przez usługę StorageLibraryChangeTracker.

Funkcja StorageLibraryChangeTracker działa w przypadku bibliotek użytkowników lub dowolnego folderu na komputerze lokalnym. Dotyczy to dysków pomocniczych lub dysków wymiennych, ale nie obejmuje dysków NAS ani dysków sieciowych.

Korzystanie z monitora zmian

Rejestr zmian jest implementowany w systemie jako bufor cykliczny przechowujący ostatnie operacje systemu plików N. Aplikacje mogą odczytywać zmiany z buforu, a następnie przetwarzać je we własnych doświadczeniach. Aplikacja po zakończeniu przetwarzania zmian oznacza je jako przetworzone i nigdy nie będzie ich ponownie rozpatrywać.

Aby użyć monitora zmian w folderze, wykonaj następujące kroki:

  1. Włącz śledzenie zmian dla folderu.
  2. Poczekaj na zmiany.
  3. Przeczytaj zmiany.
  4. Zaakceptuj zmiany.

W następnych sekcjach opisano poszczególne kroki z przykładami kodu. Kompletny przykład kodu znajduje się na końcu artykułu.

Włączanie monitora zmian

Pierwszą rzeczą, którą aplikacja musi zrobić, jest powiedzenie systemowi, że interesuje go śledzenie zmian w danej bibliotece. Robi to, wywołując metodę Enable w narzędziu śledzącym zmiany dla interesującej biblioteki.

StorageLibrary videosLib = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
StorageLibraryChangeTracker videoTracker = videosLib.ChangeTracker;
videoTracker.Enable();

Kilka ważnych uwag:

  • Przed utworzeniem obiektu StorageLibrary upewnij się, że aplikacja ma uprawnienia do poprawnej biblioteki w manifeście. Aby uzyskać więcej informacji, zobacz Uprawnienia dostępu do plików .
  • Włączenie jest bezpieczne dla wątków, nie resetuje wskaźnika i można go wywoływać tyle razy, ile się chce (więcej na ten temat później).

włączanie pustego rejestratora zmian

Czekaj na zmiany

Po zainicjowaniu monitora zmian rozpocznie się rejestrowanie wszystkich operacji wykonywanych w bibliotece, nawet jeśli aplikacja nie jest uruchomiona. Aplikacje można zarejestrować do aktywacji przy każdej zmianie, rejestrując je na zdarzenie StorageLibraryChangedTrigger.

Zmiany dodawane do monitora zmian bez odczytywania ich przez aplikację

Przeczytaj zmiany

Aplikacja może następnie sondować zmiany z monitora zmian i otrzymywać listę zmian od czasu ostatniego sprawdzenia. Poniższy kod pokazuje, jak uzyskać listę zmian z monitora zmian.

StorageLibrary videosLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
videosLibrary.ChangeTracker.Enable();
StorageLibraryChangeReader videoChangeReader = videosLibrary.ChangeTracker.GetChangeReader();
IReadOnlyList changeSet = await changeReader.ReadBatchAsync();

Aplikacja jest następnie odpowiedzialna za przetwarzanie zmian we własnym środowisku lub bazie danych zgodnie z potrzebami.

odczytywanie zmian z monitora zmian w bazie danych aplikacji

Wskazówka

Drugie wywołanie włączenia polega na obronie przed warunkiem wyścigu, jeśli użytkownik doda inny folder do biblioteki podczas odczytywania zmian w aplikacji. Bez dodatkowego wywołania Włącz kod zakończy się niepowodzeniem z ecSearchFolderScopeViolation (0x80070490), jeśli użytkownik zmienia foldery w swojej bibliotece

Zaakceptuj zmiany

Po zakończeniu przetwarzania zmian aplikacja powinna poinformować system, aby nigdy nie pokazywał tych zmian ponownie, wywołując metodę AcceptChangesAsync .

await changeReader.AcceptChangesAsync();

Oznaczanie zmian jako przeczytane, aby nigdy nie były wyświetlane ponownie

Aplikacja będzie teraz otrzymywać nowe zmiany tylko podczas odczytywania monitora zmian w przyszłości.

  • Jeśli zmiany wystąpiły między wywołaniem ReadBatchAsync i AcceptChangesAsync, wskaźnik zostanie zaawansowany tylko do najnowszej zmiany widocznej w aplikacji. Te inne zmiany będą nadal dostępne przy następnym wywołaniu ReadBatchAsync.
  • Nieakceptowanie zmian spowoduje, że system zwróci ten sam zestaw zmian przy następnym wywołaniu aplikacji ReadBatchAsync.

Ważne rzeczy do zapamiętania

W przypadku korzystania z trackera zmian należy pamiętać o kilku kwestiach, aby upewnić się, że wszystko działa prawidłowo.

Przepełnienia bufora

Mimo że staramy się zarezerwować wystarczającą ilość miejsca w śledzeniu zmian, aby przechowywać wszystkie operacje wykonywane w systemie do momentu ich odczytania przez aplikację, bardzo łatwo sobie wyobrazić scenariusz, w którym aplikacja nie odczytuje zmian przed nadpisaniem bufora cyklicznego. Zwłaszcza jeśli użytkownik przywraca dane z kopii zapasowej lub synchronizuje dużą kolekcję zdjęć ze smartfona.

W takim przypadku narzędzie ReadBatchAsync zwróci kod błędu StorageLibraryChangeType.ChangeTrackingLost. Jeśli aplikacja otrzymuje ten kod błędu, oznacza to kilka rzeczy:

  • Bufor nadpisał się od czasu ostatniego przyjrzenia się temu. Najlepszym działaniem jest ponowne przeszukiwanie biblioteki, ponieważ wszelkie informacje z trackera będą niekompletne.
  • Monitor zmian nie zwróci żadnych kolejnych zmian, dopóki nie wywołasz Resetuj. Po wywołaniu resetu przez aplikację, wskaźnik zostanie przeniesiony do ostatniej zmiany, a śledzenie zostanie wznowione jak zwykle.

Te przypadki powinny być rzadkie, ale w scenariuszach, w których użytkownik przenosi dużą liczbę plików na dysku, nie chcemy, aby monitor zmian się rozrastał i zajmował zbyt dużo przestrzeni dyskowej. Powinno to pozwolić aplikacjom reagować na ogromne operacje systemu plików, nie uszkadzając środowiska klienta w systemie Windows.

Zmiany w bibliotece pamięci masowej

Klasa StorageLibrary istnieje jako wirtualna grupa folderów głównych, które zawierają inne foldery. Aby uzgodnić to z monitorem zmian systemu plików, dokonaliśmy następujących wyborów:

  • Wszelkie zmiany w potomnych folderach biblioteki głównej zostaną odzwierciedlone w monitorze zmian. Foldery biblioteki głównej można znaleźć przy użyciu właściwości Foldery .
  • Dodawanie lub usuwanie folderów głównych z biblioteki StorageLibrary (za pośrednictwem elementu RequestAddFolderAsync i RequestRemoveFolderAsync) nie spowoduje utworzenia wpisu w monitorze zmian. Zmiany te można śledzić za pomocą zdarzenia DefinitionChanged lub wyliczając główne foldery w bibliotece przy użyciu właściwości foldery.
  • Jeśli do biblioteki dodawany jest folder z zawartością, która już się w nim znajduje, nie zostanie wygenerowane powiadomienie o zmianie ani wpisy śledzenia zmian. Wszelkie kolejne zmiany elementów podrzędnych tego folderu będą generować powiadomienia i wpisy w monitorze zmian.

Wywoływanie metody Enable

Aplikacje powinny wywoływać Włącz natychmiast po rozpoczęciu śledzenia systemu plików i przed każdym wyliczeniem zmian. Dzięki temu wszystkie zmiany zostaną przechwycone przez monitor zmian.

Składanie całości

Oto cały kod używany do rejestrowania zmian w bibliotece wideo i rozpoczynanie ściągania zmian z monitora zmian.

private async void EnableChangeTracker()
{
    StorageLibrary videosLib = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
    StorageLibraryChangeTracker videoTracker = videosLib.ChangeTracker;
    videoTracker.Enable();
}

private async void GetChanges()
{
    StorageLibrary videosLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
    videosLibrary.ChangeTracker.Enable();
    StorageLibraryChangeReader videoChangeReader = videosLibrary.ChangeTracker.GetChangeReader();
    IReadOnlyList changeSet = await changeReader.ReadBatchAsync();


    //Below this line is for the blog post. Above the line is for the magazine
    foreach (StorageLibraryChange change in changeSet)
    {
        if (change.ChangeType == StorageLibraryChangeType.ChangeTrackingLost)
        {
            //We are in trouble. Nothing else is going to be valid.
            log("Resetting the change tracker");
            videosLibrary.ChangeTracker.Reset();
            return;
        }
        if (change.IsOfType(StorageItemTypes.Folder))
        {
            await HandleFileChange(change);
        }
        else if (change.IsOfType(StorageItemTypes.File))
        {
            await HandleFolderChange(change);
        }
        else if (change.IsOfType(StorageItemTypes.None))
        {
            if (change.ChangeType == StorageLibraryChangeType.Deleted)
            {
                RemoveItemFromDB(change.Path);
            }
        }
    }
    await changeReader.AcceptChangesAsync();
}