Dela via


Spåra filsystemändringar i bakgrunden

viktiga API:er

Klassen StorageLibraryChangeTracker gör det möjligt för appar att spåra ändringar i filer och mappar när användare flyttar dem runt i systemet. Med klassen StorageLibraryChangeTracker kan en app spåra:

  • Filåtgärder som att lägga till, ta bort, ändra.
  • Mappåtgärder som namnbyten och borttagningar.
  • Filer och mappar som flyttas på enheten.

Använd den här guiden för att lära dig programmeringsmodellen för att arbeta med ändringsspåraren, visa exempelkod och förstå de olika typer av filåtgärder som spåras av StorageLibraryChangeTracker.

StorageLibraryChangeTracker funkar för användarbibliotek eller för valfri mapp på den lokala datorn. Detta omfattar sekundära enheter eller flyttbara enheter men inkluderar inte NAS-enheter eller nätverksenheter.

Så här använder du ändringsspåraren

Ändringsspåraren implementeras i systemet som en cirkulär buffert som lagrar de senaste N-filsystemåtgärderna. Appar kan läsa ändringarna från bufferten och sedan bearbeta dem till sina egna upplevelser. När appen är klar med ändringarna markerar den ändringarna som bearbetade och kommer aldrig att se dem igen.

Följ dessa steg om du vill använda ändringsspåraren i en mapp:

  1. Aktivera ändringsspårning för mappen.
  2. Vänta på ändringar.
  3. Läs ändringar.
  4. Acceptera ändringar.

Nästa avsnitt går igenom vart och ett av stegen med några kodexempel. Det fullständiga kodexemplet finns i slutet av artikeln.

Aktivera ändringsspåraren

Det första som appen behöver göra är att berätta för systemet att den är intresserad av ändringsspårning av ett visst bibliotek. Det gör det genom att anropa metoden Aktivera i ändringsspåraren för biblioteket av intresse.

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

Några viktiga kommentarer:

Aktivera en tom ändringsspårare

Vänta på ändringar

När ändringsspåraren har initierats börjar den registrera alla åtgärder som utförs i ett bibliotek, även om appen inte körs. Appar kan registrera sig för att bli aktiverade när en ändring sker genom att registrera sig för händelsen StorageLibraryChangedTrigger.

Ändringar som läggs till i ändringsspåraren utan att appen läser dem

Läs ändringarna

Appen kan sedan söka efter ändringar från ändringsspåraren och ta emot en lista över ändringarna sedan den senast kontrollerades. Koden nedan visar hur du hämtar en lista över ändringar från ändringsspåraren.

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

Appen ansvarar sedan för att bearbeta ändringarna till sin egen upplevelse eller databas efter behov.

Läsa ändringarna från ändringsspåraren till en appdatabas

Tips/Råd

Det andra anropet för att aktivera är att försvara mot ett konkurrensvillkor om användaren lägger till en annan mapp i biblioteket medan appen läser ändringar. Utan det extra anropet till Aktivera misslyckas koden med ecSearchFolderScopeViolation (0x80070490) om användaren ändrar mapparna i sitt bibliotek

Acceptera ändringarna

När appen har bearbetat ändringarna bör den uppmana systemet att aldrig visa ändringarna igen genom att anropa metoden AcceptChangesAsync .

await changeReader.AcceptChangesAsync();

Markera ändringar som lästa så att de aldrig visas igen

Appen får nu bara nya ändringar när du läser ändringsspåraren i framtiden.

  • Om ändringar har gjorts mellan att anropa ReadBatchAsync och AcceptChangesAsync, kommer pekaren endast att avanceras till den senaste ändringen som appen har sett. De andra ändringarna är fortfarande tillgängliga nästa gång de anropar ReadBatchAsync.
  • Om ändringarna inte godkänns returnerar systemet samma uppsättning ändringar nästa gång appen anropar ReadBatchAsync.

Viktiga saker att komma ihåg

När du använder ändringsspåraren finns det några saker som du bör tänka på för att se till att allt fungerar korrekt.

Buffertöverskridningar

Även om vi försöker reservera tillräckligt med utrymme i ändringsspåraren för att lagra alla åtgärder som sker i systemet tills appen kan läsa dem, är det mycket enkelt att föreställa sig ett scenario där appen inte läser ändringarna innan den cirkulära bufferten skriver över sig själv. Särskilt om användaren återställer data från en säkerhetskopia eller synkroniserar en stor samling bilder från sin kameratelefon.

I det här fallet returnerar ReadBatchAsync felkoden StorageLibraryChangeType.ChangeTrackingLost. Om din app får den här felkoden innebär det några saker:

  • Bufferten har skrivits över sedan du senast granskade den. Det bästa sättet är att söka igenom biblioteket igen, eftersom all information från spåraren är ofullständig.
  • Ändringsspåraren returnerar inte fler ändringar förrän du anropar Återställ. När appen anropar återställning flyttas pekaren till den senaste ändringen och spårningen återupptas normalt.

Det bör vara ovanligt att få dessa fall, men i scenarier där användaren flyttar ett stort antal filer runt på sin disk vill vi inte att ändringsspåraren ska ballonga och ta upp för mycket lagringsutrymme. Detta bör göra det möjligt för appar att reagera på massiva filsystemåtgärder utan att skada kundupplevelsen i Windows.

Ändringar i en StorageLibrary

Klassen StorageLibrary finns som en virtuell grupp med rotmappar som innehåller andra mappar. För att stämma av detta med en filsystemsändringsspårare gjorde vi följande val:

  • Ändringar i underordnade mappar tillhörande rotbiblioteket kommer att representeras i ändringsspåraren. Rotbiblioteksmapparna finns med hjälp av egenskapen Mappar .
  • Om du lägger till eller tar bort rotmappar från en StorageLibrary (via RequestAddFolderAsync och RequestRemoveFolderAsync) skapas ingen post i ändringsspåraren. Dessa ändringar kan spåras via händelsen DefinitionChanged eller genom att räkna upp rotmapparna i biblioteket med hjälp av egenskapen Mappar .
  • Om en mapp med innehåll som redan finns i den läggs till i biblioteket genereras inga ändringsmeddelanden eller ändringsspårarposter. Eventuella efterföljande ändringar av underordnade i den mappen genererar meddelanden och ändrar spårningsposter.

Anropa metoden Aktivera

Appar bör anropa Aktivera så snart de börjar spåra filsystemet och före varje uppräkning av ändringarna. Detta säkerställer att alla ändringar registreras av ändringsspåraren.

Sätta ihop det

Här är all kod som används för att registrera ändringarna från videobiblioteket och börja hämta ändringarna från ändringsspåraren.

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