Sdílet prostřednictvím


Sledování změn systému souborů na pozadí

důležitá rozhraní API

Třída StorageLibraryChangeTracker umožňuje aplikacím sledovat změny v souborech a složkách, jak je uživatelé pohybují po systému. Pomocí třídy StorageLibraryChangeTracker může aplikace sledovat:

  • Operace se soubory, včetně přidání, odstranění, úpravy.
  • Operace složek, jako jsou přejmenování a odstranění.
  • Přesun souborů a složek na disku.

V tomto průvodci se dozvíte programovací model pro práci s sledováním změn, zobrazením ukázkového kódu a pochopením různých typů operací se soubory, které jsou sledovány StorageLibraryChangeTracker.

StorageLibraryChangeTracker funguje pro uživatelské knihovny nebo pro jakoukoli složku na místním počítači. To zahrnuje sekundární jednotky nebo vyměnitelné jednotky, ale nezahrnuje jednotky NAS ani síťové jednotky.

Použití sledování změn

Sledování změn se implementuje v systému jako kruhová vyrovnávací paměť, která ukládá poslední N operací systému souborů. Aplikace si mohou přečíst změny z bufferu a pak je zpracovat do vlastních funkcí. Jakmile aplikace dokončí změny, označí změny jako zpracované a už je neuvidí.

Pokud chcete použít sledování změn ve složce, postupujte takto:

  1. Povolte sledování změn pro složku.
  2. Počkejte na změny.
  3. Přečtěte si změny.
  4. Přijměte změny.

Následující části projdou jednotlivými kroky s příklady kódu. Kompletní ukázka kódu je k dispozici na konci článku.

Povolení sledování změn

První věcí, kterou aplikace potřebuje udělat, je informovat systém, že má zájem o sledování změn v dané knihovně. Toto provede tím, že zavolá metodu Enable na sledovači změn pro danou knihovnu.

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

Několik důležitých poznámek:

  • Před vytvořením objektu StorageLibrary se ujistěte, že vaše aplikace má v manifestu oprávnění ke správné knihovně. Další podrobnosti najdete v tématu Oprávnění k přístupu k souborům.
  • Povolit je bezpečné pro vlákno, neobnoví ukazatel a můžete volat tolikrát, kolikrát chcete (více o tom později).

Povolení sledování změn s prázdným stavem

Čekání na změny

Po inicializaci sledování změn začne zaznamenávat všechny operace, ke kterým dochází v knihovně, i když aplikace není spuštěná. Aplikace se mohou zaregistrovat pro aktivaci při každé změně tím, že se přihlásí k události StorageLibraryChangedTrigger.

Změny se přidávají do sledování změn, aniž by je aplikace četla

Přečtěte si změny

Aplikace se pak může dotazovat na změny ze sledování změn a přijímat seznam změn od poslední kontroly. Následující kód ukazuje, jak získat seznam změn ze sledování změn.

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

Aplikace pak podle potřeby zodpovídá za zpracování změn do vlastního prostředí nebo databáze.

Načítání změn ze sledovače změn do databáze aplikace

Návod

Druhým voláním, které povolíte, je zabránit kolizi, pokud uživatel přidá do knihovny další složku, zatímco vaše aplikace čte změny. Bez dalšího volání Enable kód selže s ecSearchFolderScopeViolation (0x80070490), pokud uživatel mění složky v knihovně.

Přijmout změny

Po dokončení zpracování změn by měla aplikace informovat systém, aby tyto změny už znovu nezobrazoval, voláním metody AcceptChangesAsync.

await changeReader.AcceptChangesAsync();

označení změn jako přečtené, takže se už nikdy nezobrazí

Aplikace teď bude přijímat nové změny jenom při čtení sledovače změn v budoucnu.

  • Pokud proběhly změny mezi voláním ReadBatchAsync a AcceptChangesAsync, ukazatel bude posunut pouze k nejnovější změně, kterou aplikace zaznamenala. Tyto další změny budou stále k dispozici při příštím volání ReadBatchAsync.
  • Nepřijmutí změn způsobí, že systém vrátí stejnou sadu změn při příštím volání aplikace ReadBatchAsync.

Důležité věci k zapamatování

Při použití sledování změn existuje několik věcí, které byste měli mít na paměti, abyste měli jistotu, že všechno funguje správně.

Přetečení vyrovnávací paměti

I když se snažíme rezervovat dostatek místa v změnovém sledovači, aby všechny operace, které probíhají v systému, než je vaše aplikace může přečíst, je velmi snadné si představit scénář, kdy aplikace nepřečte změny dříve, než je kruhová vyrovnávací paměť přepíše. Zvláště pokud uživatel obnovuje data ze zálohy nebo synchronizuje velkou kolekci obrázků z telefonu fotoaparátu.

V tomto případě ReadBatchAsync vrátí kód chyby StorageLibraryChangeType.ChangeTrackingLost. Pokud aplikace obdrží tento kód chyby, znamená to několik věcí:

  • Vyrovnávací paměť se přepsala od posledního okamžiku, kdy jste se na ni podívali. Nejlepší postup je znovu projít knihovnu, protože všechny informace z trackeru budou neúplné.
  • Sledování změn nebude vracet žádné další změny, dokud nezavoláte Resetovat. Po volání resetu aplikací se ukazatel přesune na nejnovější změnu a sledování bude normálně pokračovat.

Tyto případy by měly být vzácné, ale ve scénářích, kdy uživatel přesouvá velký počet souborů na svém disku, nechceme, aby se sledování změn nadměrně zvětšilo a zabralo příliš mnoho úložného prostoru. To by mělo aplikacím umožnit reagovat na rozsáhlé operace systému souborů, aniž by tím došlo k poškození prostředí zákazníka ve Windows.

Změny v úložišti

Třída StorageLibrary existuje jako virtuální skupina kořenových složek, které obsahují další složky. Abychom to mohli sladit se sledováním změn systému souborů, provedli jsme následující volby:

  • Všechny změny podřízených složek kořenové knihovny budou reprezentovány ve sledování změn. Kořenové složky knihovny můžete nalézt pomocí vlastnosti Folders.
  • Přidání nebo odebrání kořenových složek z StorageLibrary (prostřednictvím RequestAddFolderAsync a RequestRemoveFolderAsync) nevytvoří položku v sledování změn. Tyto změny lze sledovat prostřednictvím události DefinitionChanged nebo procházením kořenových složek v knihovně pomocí vlastnosti Složky.
  • Pokud je složka s obsahem již přidaná do knihovny, nebudou vygenerována žádná oznámení o změnách ani položky sledování změn. Všechny následné změny potomků této složky budou generovat oznámení a položky sledování změn.

Volání metody Enable

Aplikace by měly volat Aktivovat, jakmile začnou sledovat systém souborů, a to před každým výčtem změn. Tím zajistíte, že sledování změn zachytí všechny změny.

Dáváme to dohromady

Tady je veškerý kód, který slouží k registraci změn z knihovny videí a zahájení načítání změn z sledování změn.

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();
}