Compartir a través de


Seguimiento de los cambios del sistema de archivos en segundo plano

Las APIs importantes

La clase StorageLibraryChangeTracker permite a las aplicaciones realizar un seguimiento de los cambios en archivos y carpetas a medida que los usuarios los mueven por el sistema. Con la clase StorageLibraryChangeTracker, una aplicación puede realizar un seguimiento de:

  • Operaciones de archivo, como agregar, eliminar, modificar.
  • Operaciones de carpeta como cambios de nombre y eliminaciones.
  • Archivos y carpetas moviéndose en la unidad.

Use esta guía para obtener información sobre el modelo de programación para trabajar con el seguimiento de cambios, ver código de ejemplo y comprender los distintos tipos de operaciones de archivo que realiza el seguimiento de StorageLibraryChangeTracker.

storageLibraryChangeTracker funciona para las bibliotecas de usuario o para cualquier carpeta del equipo local. Esto incluye unidades secundarias o unidades extraíbles, pero no incluye unidades NAS ni unidades de red.

Uso del seguimiento de cambios

El seguimiento de cambios se implementa en el sistema como un búfer circular que almacena las últimas N operaciones del sistema de archivos. Las aplicaciones pueden leer los cambios del búfer y, a continuación, procesarlos para integrarlos en sus propias funcionalidades. Una vez finalizada la aplicación con los cambios, marca los cambios como procesados y nunca los volverá a ver.

Para usar el rastreador de cambios en una carpeta, siga estos pasos:

  1. Habilite el seguimiento de cambios para la carpeta.
  2. Espere a que se produzcan cambios.
  3. Lee los cambios.
  4. Aceptar cambios.

En las secciones siguientes se explica cada uno de los pasos con algunos ejemplos de código. El ejemplo de código completo se proporciona al final del artículo.

Habilitación del seguimiento de cambios

Lo primero que debe hacer la aplicación es indicar al sistema que está interesado en el seguimiento de cambios de una biblioteca determinada. Para ello, llama al método Enable en el rastreador de cambios de la biblioteca de interés.

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

Algunas notas importantes:

  • Asegúrese de que la aplicación tiene permiso para la biblioteca correcta en el manifiesto antes de crear el objeto StorageLibrary. Consulte permisos de acceso a archivos para obtener más información.
  • Habilitar es seguro para subprocesos, no restablecerá el puntero y se puede llamar tantas veces como quiera (más adelante).

Activación de un rastreador de cambios vacío

Esperar cambios

Una vez inicializado el seguimiento de cambios, comenzará a registrar todas las operaciones que se producen dentro de una biblioteca, incluso mientras la aplicación no se está ejecutando. Las aplicaciones se pueden registrar para activarse en cualquier momento en que haya un cambio, inscribiéndose en el evento StorageLibraryChangedTrigger.

cambios que se agregan al rastreador de cambios sin que la aplicación los lea

Leer los cambios

A continuación, la aplicación puede consultar los cambios del rastreador de cambios y recibir una lista de los cambios desde la última vez que se verificó. El código siguiente muestra cómo obtener una lista de cambios del rastreador de cambios.

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

La aplicación es responsable de procesar los cambios en su propia experiencia o base de datos según sea necesario.

Lectura de los cambios del seguimiento de cambios en una base de datos de la aplicación

Sugerencia

La segunda llamada a habilitar es defenderse contra una condición de carrera si el usuario agrega otra carpeta a la biblioteca mientras la aplicación lee los cambios. Sin la llamada adicional a Habilitar se producirá un error en el código con ecSearchFolderScopeViolation (0x80070490) si el usuario cambia las carpetas de su biblioteca.

Aceptar los cambios

Una vez que la aplicación haya terminado de procesar los cambios, debe indicar al sistema que nunca vuelva a mostrar esos cambios llamando al método AcceptChangesAsync.

await changeReader.AcceptChangesAsync();

Marcar los cambios como leídos para que nunca se vuelvan a mostrar

La aplicación ahora solo recibirá nuevos cambios al leer el rastreador de cambios.

  • Si se han producido cambios entre llamar a ReadBatchAsync y AcceptChangesAsync, el puntero solo avanzará al cambio más reciente que haya detectado la aplicación. Esos otros cambios seguirán estando disponibles la próxima vez que llame a ReadBatchAsync.
  • No aceptar los cambios hará que el sistema devuelva el mismo conjunto de cambios la próxima vez que la aplicación llame a ReadBatchAsync.

Cosas importantes que recordar

Al usar el rastreador de cambios, hay algunas cosas que debe tener en cuenta para asegurarse de que todo funciona correctamente.

Saturaciones de búfer

Aunque intentamos reservar espacio suficiente en el rastreador de cambios para contener todas las operaciones que se producen en el sistema hasta que la aplicación pueda leerlas, es muy fácil imaginar un escenario en el que la aplicación no lee los cambios antes de que el búfer circular sobrescriba en sí mismo. Especialmente si el usuario está restaurando datos desde una copia de seguridad o sincronizando una gran colección de imágenes desde su teléfono de cámara.

En este caso, ReadBatchAsync devolverá el código de error StorageLibraryChangeType.ChangeTrackingLost. Si la aplicación recibe este código de error, significa un par de cosas:

  • El buffer se ha reescrito desde la última vez que lo revisaste. El mejor curso de acción es explorar nuevamente la biblioteca, ya que cualquier información del rastreador estará incompleta.
  • El rastreador de cambios no devolverá más cambios hasta que llame a Reset. Una vez que la aplicación llama al restablecimiento, el puntero se moverá al cambio más reciente y el seguimiento se reanudará normalmente.

Debe ser poco frecuente obtener estos casos, pero en escenarios en los que el usuario mueve un gran número de archivos en su disco, no queremos que el rastreador de cambios se expanda excesivamente y ocupe demasiado espacio de almacenamiento. Esto debe permitir que las aplicaciones reaccionen a operaciones masivas del sistema de archivos, a la vez que no dañan la experiencia del cliente en Windows.

Cambios en storageLibrary

La clase storageLibrary de existe como un grupo virtual de carpetas raíz que contienen otras carpetas. Para conciliar esto con un rastreador de cambios del sistema de archivos, hemos tomado las siguientes opciones:

  • Los cambios en el descendiente de las carpetas de la biblioteca raíz se representarán en el rastreador de cambios. Las carpetas de la biblioteca raíz se pueden encontrar mediante la propiedad Carpetas .
  • Agregar o quitar carpetas raíz de un StorageLibrary (a través de RequestAddFolderAsync y RequestRemoveFolderAsync) no creará una entrada en el rastreador de cambios. Estos cambios se pueden seguir a través del evento DefinitionChanged o enumerando las carpetas raíz de la biblioteca usando la propiedad Carpetas de .
  • Si ya hay una carpeta con contenido en ella agregada a la biblioteca, no habrá ninguna notificación de cambios ni entradas de seguimiento de cambios generadas. Los cambios posteriores en los descendientes de esa carpeta generarán notificaciones y entradas de seguimiento de cambios.

Llamada al método Enable

Las aplicaciones deben llamar a Habilitar tan pronto como empiecen a realizar el seguimiento del sistema de archivos y antes de cada enumeración de los cambios. Esto garantizará que el rastreador de cambios capture todos los cambios.

Ensamblándolo

Este es todo el código que se utiliza para registrarse para las actualizaciones de la biblioteca de vídeos y comenzar a recuperar los cambios del rastreador de cambios.

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