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 při jejich přesouvání po systému. Tato rozhraní API WinRT je možné použít z aplikací WinUI 3 vytvořených pomocí Windows App SDK cílení na Windows 10 verze 1809 (build 17763) nebo novější. Základní rozhraní API StorageLibraryChangeTracker je k dispozici od Windows 10 verze 1803 (build 17134). Pomocí třídy StorageLibraryChangeTracker může aplikace sledovat:

  • Operace se soubory, včetně přidání, odstranění, úpravy.
  • Operace se složkami, jako je přejmenování a mazání.
  • Soubory a složky pohybující se na jednotce

V této příručce se seznámíte s programovacím modelem pro práci se sledováním změn, zobrazením ukázkového kódu a pochopením různých typů operací se soubory, které sleduje 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.

Předpoklady

  • Aplikace WinUI 3 zacílena na Windows 10, verze 1809 nebo novější – Windows App SDK / WinUI 3 je podporován od Windows 10 verze 1809 (build 17763). Základní rozhraní API StorageLibraryChangeTracker vyžaduje Windows 10 verze 1803 (build 17134). Pokud vytváříte nový projekt, nastavte v .csproj souboru minimální verzi odpovídajícím způsobem.

  • Požadované using direktivy

    using Windows.Storage;
    
  • Deklarace schopností – Aplikace musí deklarovat příslušné schopnosti knihovny ve svém Package.appxmanifest před přístupem k StorageLibrary. Podrobnosti najdete v tématu Přístupová oprávnění k souborům .

Použití sledování změn

Sledování změn je implementováno v systému jako kruhová vyrovnávací paměť ukládající poslední N operace systému souborů. Aplikace si můžou přečíst změny z vyrovnávací paměti 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ě. Provede to voláním metody Enable na sledování změn pro požadovanou 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 Package.appxmanifest se ujistěte, že vaše aplikace deklarovala příslušnou funkci knihovny. Další podrobnosti najdete v tématu Přístupová oprávnění k souborům .
  • Povolit je thread-safe, neobnoví váš ukazatel a můžete ho volat tolikrát, kolikrát chcete (více o tom později).

Povolení prázdného sledovače změn

Č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 můžou zaregistrovat, aby se aktivovaly kdykoli, když dojde ke změně, a to registrací události StorageLibraryChangedTrigger .

Změny přidané do sledování změn bez toho, aby 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<StorageLibraryChange> changeSet = await videoChangeReader.ReadBatchAsync();

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

Čtení změn z nástroje pro sledování změn do databáze aplikace

Návod

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

Přijmout změny

Po dokončení zpracování změn by měl systému oznámit, aby tyto změny znovu nezobrazil, voláním metody AcceptChangesAsync.

await videoChangeReader.AcceptChangesAsync();

Označení změn jako přečtených, aby se už nikdy nezobrazily

Aplikace nyní bude přijímat nové změny pouze při čtení sledovače změn od této chvíle.

  • Pokud došlo k změnám mezi voláním ReadBatchAsync a AcceptChangesAsync, ukazatel bude rozšířen pouze na nejnovější změnu, která aplikace viděla. 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í ReadBatchAsync aplikace.

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 trackeru změn, aby pojmul všechny operace, které probíhají v systému, do doby, 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, než se 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 sama od té doby, co jste se na ni naposledy podívali. Nejlepší postup je znovu projít knihovnu, protože všechny informace z trackeru budou neúplné.
  • Sledování změn nevrátí žádné další změny, dokud nezavoláte Resetovat. Po zavolá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 sledování změn narostlo a zabíralo 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 StorageLibrary

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 sestupně složek kořenové knihovny budou reprezentovány v sledování změn. Složky kořenové knihovny lze najít pomocí vlastnosti Složky .
  • 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 výčet 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 Povolit jakmile začnou sledovat systém souborů a 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<StorageLibraryChange> changeSet = await videoChangeReader.ReadBatchAsync();

    foreach (StorageLibraryChange change in changeSet)
    {
        if (change.ChangeType == StorageLibraryChangeType.ChangeTrackingLost)
        {
            // The circular buffer overflowed. Recrawl the library from scratch.
            videosLibrary.ChangeTracker.Reset();
            return;
        }
        if (change.IsOfType(StorageItemTypes.File))
        {
            await HandleFileChange(change);
        }
        else if (change.IsOfType(StorageItemTypes.Folder))
        {
            await HandleFolderChange(change);
        }
        else if (change.IsOfType(StorageItemTypes.None))
        {
            if (change.ChangeType == StorageLibraryChangeType.Deleted)
            {
                RemoveItemFromDB(change.Path);
            }
        }
    }
    await videoChangeReader.AcceptChangesAsync();
}