Compartilhar via


Acompanhar as alterações do sistema de arquivos em segundo plano

APIs importantes

A classe StorageLibraryChangeTracker permite que os aplicativos acompanhem as alterações em arquivos e pastas à medida que os usuários as movem pelo sistema. Usando a classe StorageLibraryChangeTracker, um aplicativo pode acompanhar:

  • Operações de arquivo, incluindo adicionar, excluir, modificar.
  • Operações de pasta, como renomeações e exclusões.
  • Arquivos e pastas em movimento na unidade.

Use este guia para aprender o modelo de programação para trabalhar com o rastreador de alterações, exibir algum código de exemplo e entender os diferentes tipos de operações de arquivo que são controladas por StorageLibraryChangeTracker.

StorageLibraryChangeTracker funciona para bibliotecas de usuário ou para qualquer pasta no computador local. Isso inclui unidades secundárias ou unidades removíveis, mas não inclui unidades NAS ou unidades de rede.

Usando o rastreador de alterações

O rastreador de alterações é implementado no sistema como um buffer circular armazenando as últimas N operações do sistema de arquivos. Os aplicativos podem ler as alterações fora do buffer e processá-las em suas próprias experiências. Depois que o aplicativo for concluído com as alterações, ele marcará as alterações como processadas e nunca mais as verá novamente.

Para usar o rastreador de alterações em uma pasta, siga estas etapas:

  1. Habilite o controle de alterações para a pasta.
  2. Aguarde as alterações.
  3. Ler alterações.
  4. Aceite alterações.

As próximas seções percorrem cada uma das etapas com alguns exemplos de código. O exemplo de código completo é fornecido no final do artigo.

Habilitar o rastreador de alterações

A primeira coisa que o aplicativo precisa fazer é dizer ao sistema que ele está interessado em alterar o controle de uma determinada biblioteca. Ele faz isso chamando o método Enable no rastreador de alterações da biblioteca em questão.

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

Algumas notas importantes:

  • Verifique se seu aplicativo tem permissão para a biblioteca correta no manifesto antes de criar o objeto StorageLibrary. Consulte , permissões de acesso a arquivos, para obter mais detalhes.
  • Habilitar é thread-safe, não redefinirá o ponteiro e poderá ser chamado quantas vezes quiser (mais sobre isso posteriormente).

Habilitar um rastreador de alterações vazio

Aguardar alterações

Depois que o rastreador de alterações for inicializado, ele começará a registrar todas as operações que ocorrem dentro de uma biblioteca, mesmo enquanto o aplicativo não estiver em execução. Os aplicativos podem se registrar para serem ativados sempre que houver uma alteração registrando-se no evento StorageLibraryChangedTrigger.

Alterações que estão sendo adicionadas ao rastreador de alterações sem que o aplicativo as leia

Ler as alterações

Depois, o aplicativo pode sondar as alterações a partir do rastreador de alterações e receber uma lista das mudanças desde a última vez em que verificou. O código a seguir mostra como obter uma lista de alterações do rastreador de alterações.

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

Em seguida, o aplicativo é responsável por processar as alterações em sua própria experiência ou banco de dados, conforme necessário.

Ler as alterações do rastreador de alterações em um banco de dados de aplicativo

Dica

A segunda chamada para habilitar é defender contra uma condição de concorrência se o usuário adicionar outra pasta à biblioteca enquanto seu aplicativo estiver lendo as alterações. Sem a chamada extra para Habilitar o código falhará com ecSearchFolderScopeViolation (0x80070490) se o usuário estiver alterando as pastas em sua biblioteca

Aceitar as alterações

Depois que o aplicativo terminar de processar as alterações, ele deverá informar ao sistema para nunca mais mostrar essas alterações chamando o método AcceptChangesAsync.

await changeReader.AcceptChangesAsync();

Marcando alterações como lidas para que nunca mais sejam exibidas

Agora, o aplicativo receberá apenas novas alterações ao ler o rastreador de alterações no futuro.

  • Se houver alterações entre a chamada de ReadBatchAsync e AcceptChangesAsync, o ponteiro será avançado apenas para a alteração mais recente que o aplicativo percebeu. Essas outras alterações ainda estarão disponíveis na próxima vez que ele invocar ReadBatchAsync .
  • Não aceitar as alterações fará com que o sistema retorne o mesmo conjunto de alterações na próxima vez que o aplicativo chamar ReadBatchAsync .

Coisas importantes a serem lembradas

Ao usar o rastreador de alterações, há algumas coisas que você deve ter em mente para garantir que tudo esteja funcionando corretamente.

Sobrecargas de buffer

Embora tentemos reservar espaço suficiente no rastreador de alterações para manter todas as operações acontecendo no sistema até que seu aplicativo possa lê-las, é muito fácil imaginar um cenário em que o aplicativo não leia as alterações antes que o buffer circular se substitua. Especialmente se o usuário estiver restaurando dados de um backup ou sincronizando uma grande coleção de fotos da câmera do telefone.

Nesse caso, ReadBatchAsync retornará o código de erro StorageLibraryChangeType.ChangeTrackingLost . Se seu aplicativo receber esse código de erro, isso significa algumas coisas:

  • O buffer foi sobrescrito desde a última vez que você o consultou. A melhor estratégia é rastrear novamente a biblioteca, porque qualquer informação do rastreador estará incompleta.
  • O rastreador de alterações não retornará mais alterações até que você chame Redefinir. Depois que as chamadas do aplicativo forem redefinidas, o ponteiro será movido para a alteração mais recente e o acompanhamento será retomado normalmente.

Deve ser raro obter esses casos, mas em cenários em que o usuário está movendo um grande número de arquivos em seu disco, não queremos que o rastreador de alterações cresça rapidamente e ocupe muito armazenamento. Isso deve permitir que os aplicativos reajam a operações maciças do sistema de arquivos, não prejudicando a experiência do cliente no Windows.

Alterações em um StorageLibrary

A classe StorageLibrary existe como um grupo virtual de pastas raiz que contêm outras pastas. Para reconciliar isso com um rastreador de alterações do sistema de arquivos, fizemos as seguintes opções:

  • Todas as alterações no descendente das pastas da biblioteca raiz serão representadas no rastreador de alterações. As pastas da biblioteca raiz podem ser encontradas usando a propriedade Pastas.
  • Adicionar ou remover pastas raiz de uma StorageLibrary (por meio de RequestAddFolderAsync e RequestRemoveFolderAsync) não criará uma entrada no rastreador de alterações. Essas alterações podem ser controladas por meio do evento DefinitionChanged ou enumerando as pastas raiz na biblioteca usando a propriedade Folders.
  • Se uma pasta que já contém conteúdo for adicionada à biblioteca, não haverá notificação de alteração nem serão geradas entradas de rastreador de alteração. As alterações subsequentes nos descendentes dessa pasta gerarão notificações e alterarão as entradas do rastreador.

Chamando o método Enable

Os aplicativos devem chamar Habilitar assim que começarem a acompanhar o sistema de arquivos e antes de cada enumeração das alterações. Isso garantirá que todas as alterações sejam capturadas pelo rastreador de alterações.

Juntando as peças

Aqui está todo o código que é usado para registrar as alterações da biblioteca de vídeo e começar a extrair as alterações do rastreador de alterações.

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