Procédure : synchroniser des fichiers à l'aide de code managé

Cette rubrique explique comment utiliser un langage managé, tel que C# ou Visual Basic, pour créer une application qui synchronise des fichiers et des sous-dossiers en utilisant le fournisseur de synchronisation de fichiers Sync Framework.

Les exemples de cette rubrique reposent sur les types Sync Framework suivants :

Présentation de la synchronisation des fichiers

Sync Framework implémente un fournisseur de synchronisation qui peut être utilisé pour synchroniser des fichiers et sous-dossiers contenus dans un dossier dans un système de fichiers. Ce fournisseur expose plusieurs paramètres configurables pour offrir plus de contrôle sur la façon exacte dont la synchronisation se produit et les éléments qui sont synchronisés. Pour synchroniser des fichiers entre deux dossiers, une application effectue les étapes de base suivantes :

  1. Crée un objet FileSyncProvider pour représenter chaque dossier.

  2. Passe les deux fournisseurs à un objet SyncOrchestrator et spécifie l'un comme fournisseur de source et l'autre comme fournisseur de destination.

  3. Appelle Synchronize pour démarrer la session de synchronisation.

Pour plus d'informations sur la synchronisation des fichiers, consultez Synchronisation des fichiers.

Exemple

Dans l'exemple de code de cette section, une application console synchronise deux répertoires, notamment les sous-répertoires et fichiers contenus dans ces répertoires. L'exemple de code présente les tâches suivantes :

  • Définition des options de synchronisation.

  • Détection explicite des modifications d'un réplica.

  • Définition d'un filtre de contrôle des éléments qui sont inclus dans la synchronisation.

  • Gestion des conflits qui peuvent se produire pendant la synchronisation.

  • Synchronisation de deux réplicas.

À la suite de ces exemples de code, nous incluons le code complet requis pour générer et exécuter l'application.

Définition des options de synchronisation

L'objet FileSyncOptions vous permet de définir plusieurs options de synchronisation des fichiers, notamment pour déterminer comment détecter des modifications et si les éléments doivent être supprimés pendant la synchronisation ou déplacés vers la Corbeille. L'exemple de code suivant définit quatre options, dont trois d'entre elles concernent la suppression des éléments. L'option ExplicitDetectChanges signifie que Sync Framework n'effectuera aucune détection de modifications à moins que l'application n'appelle DetectChanges explicitement. Pour plus d'informations, consultez la section suivante, « Détection des modifications ».

FileSyncOptions options = FileSyncOptions.ExplicitDetectChanges |
         FileSyncOptions.RecycleDeletedFiles | FileSyncOptions.RecyclePreviousFileOnUpdates | 
         FileSyncOptions.RecycleConflictLoserFiles;
Dim options As FileSyncOptions = _
    FileSyncOptions.ExplicitDetectChanges Or FileSyncOptions.RecycleDeletedFiles _
    Or FileSyncOptions.RecyclePreviousFileOnUpdates _
    Or FileSyncOptions.RecycleConflictLoserFiles

Détection des modifications

Par défaut, Sync Framework détecte les modifications sur les deux réplicas dès que Synchronize est appelé. La détection des modifications permet à Sync Framework de déterminer quels éléments doivent être envoyés du réplica source au réplica de destination et quels éléments sont en conflit, le cas échéant. En spécifiant ExplicitDetectChanges, vous pouvez déterminer quand effectuer la détection des modifications. L'exemple de code suivant appelle la détection des modifications pour chaque réplica avant que Synchronize ne soit appelé. Cet exemple est destiné à illustrer DetectChanges, mais il présente l'avantage de comporter une seule passe de détection des modifications au lieu des deux passes requises pour la synchronisation bidirectionnelle qui sera effectuée ultérieurement dans l'application.

DetectChangesOnFileSystemReplica(
    replica1RootPath, filter, options);
DetectChangesOnFileSystemReplica(
    replica2RootPath, filter, options);
public static void DetectChangesOnFileSystemReplica(
        string replicaRootPath,
        FileSyncScopeFilter filter, FileSyncOptions options)
{
    FileSyncProvider provider = null;

    try
    {
        provider = new FileSyncProvider(replicaRootPath, filter, options);
        provider.DetectChanges();
    }
    finally
    {
        // Release resources.
        if (provider != null)
            provider.Dispose();
    }
}
DetectChangesOnFileSystemReplica(replica1RootPath, filter, options)
DetectChangesOnFileSystemReplica(replica2RootPath, filter, options)
Public Shared Sub DetectChangesOnFileSystemReplica(ByVal replicaRootPath As String, ByVal filter As FileSyncScopeFilter, _
                                                   ByVal options As FileSyncOptions)
    Dim provider As FileSyncProvider = Nothing

    Try
        provider = New FileSyncProvider(replicaRootPath, filter, options)
        provider.DetectChanges()
    Finally
        ' Release resources. 
        If provider IsNot Nothing Then
            provider.Dispose()
        End If
    End Try
End Sub

Spécification d'un filtre statique

Les filtres statiques peuvent être configurés pour exclure des fichiers par nom (y compris les noms génériques) et par attribut. Les filtres statiques peuvent également être configurés pour exclure le contenu de sous-dossiers entiers. Par ailleurs, une liste explicite de noms de fichiers à inclure (y compris les noms génériques) peut être spécifiée. Pour être inclus dans l'étendue, un fichier ou un dossier doit répondre à tous les filtres. Par exemple, si tous les fichiers qui ont une extension .txt sont exclus de l'étendue et que le fichier MyFile.txt est spécifié dans la liste des fichiers à inclure explicitement dans l'étendue, MyFile.txt sera exclu à cause de son extension .txt.

L'exemple de code suivant utilise l'objet FileSyncScopeFilter pour créer un filtre qui exclut tous les fichiers *.lnk. Un filtre n'a aucune relation avec le fournisseur qui le crée. Pour connecter un filtre à un fournisseur, passez le filtre à l'un des constructeurs de FileSyncProvider ou en définissant la propriété ScopeFilter. Dans l'exemple d'application, nous utilisons la méthode DetectChangesOnFileSystemReplica() parce que le filtre ne s'applique qu'à la détection des modifications. Étant donné que le filtre est indépendant du fournisseur, un seul filtre doit être créé par session de synchronisation ; les fournisseurs ne doivent pas utiliser plusieurs filtres différents, sous risque de provoquer une non-convergence des données.

FileSyncScopeFilter filter = new FileSyncScopeFilter();
filter.FileNameExcludes.Add("*.lnk");
Dim filter As New FileSyncScopeFilter()
filter.FileNameExcludes.Add("*.lnk")

En plus des filtres statiques, vous pouvez exclure des fichiers pendant la synchronisation en gérant un événement déclenché par le fournisseur. Pour plus d'informations, consultez Contrôle des fichiers qui sont synchronisés.

Gestion des conflits

Sync Framework détecte et résout les conflits d'accès concurrentiel et les conflits de contraintes dans les fichiers et les dossiers. Un conflit d'accès concurrentiel se produit lorsque le même élément est modifié dans les deux réplicas depuis la dernière session de synchronisation réalisée entre ces réplicas. Un conflit de contraintes se produit si un fichier ou dossier avec le même nom est ajouté aux deux réplicas. Les conflits sont résolus en conservant le fichier ou dossier avec la modification la plus récente et en supprimant (ou en déplaçant) l'autre fichier ou dossier. Pour les fichiers, vous avez également la possibilité de spécifier le gagnant du conflit (le réplica source ou le réplica de destination), indépendamment de l'heure de la modification. L'exemple de code suivant inscrit des gestionnaires d'événements pour les événements ItemConflicting et ItemConstraint qui sont disponibles via l'objet SyncCallbacks. Les méthodes appelées résolvent tous les conflits en faveur du réplica source, puis écrivent les informations sur la console.

Dim destinationCallbacks As SyncCallbacks = destinationProvider.DestinationCallbacks
AddHandler destinationCallbacks.ItemConflicting, AddressOf OnItemConflicting
AddHandler destinationCallbacks.ItemConstraint, AddressOf OnItemConstraint
SyncCallbacks destinationCallbacks = destinationProvider.DestinationCallbacks;
destinationCallbacks.ItemConflicting += new EventHandler<ItemConflictingEventArgs>(OnItemConflicting);
destinationCallbacks.ItemConstraint += new EventHandler<ItemConstraintEventArgs>(OnItemConstraint);
public static void OnItemConflicting(object sender, ItemConflictingEventArgs args)
{
    args.SetResolutionAction(ConflictResolutionAction.SourceWins);
    Console.WriteLine("-- Concurrency conflict detected for item " + args.DestinationChange.ItemId.ToString());
}

public static void OnItemConstraint(object sender, ItemConstraintEventArgs args)
{
    args.SetResolutionAction(ConstraintConflictResolutionAction.SourceWins);
    Console.WriteLine("-- Constraint conflict detected for item " + args.DestinationChange.ItemId.ToString());
}
Public Shared Sub OnItemConflicting(ByVal sender As Object, ByVal args As ItemConflictingEventArgs)
    args.SetResolutionAction(ConflictResolutionAction.SourceWins)
    Console.WriteLine("-- Concurrency conflict detected for item " & args.DestinationChange.ItemId.ToString())
End Sub

Public Shared Sub OnItemConstraint(ByVal sender As Object, ByVal args As ItemConstraintEventArgs)
    args.SetResolutionAction(ConstraintConflictResolutionAction.SourceWins)
    Console.WriteLine("-- Constraint conflict detected for item " & args.DestinationChange.ItemId.ToString())
End Sub

Synchronisation de deux réplicas

Une fois que les options et les filtres sont définis, l'application synchronise les deux réplicas en instanciant un SyncOrchestrator, puis en appelant la méthode Synchronize. L'exemple de code suivant spécifie le fournisseur de chaque réplica, définit les options, inscrit les gestionnaires d'événements, spécifie une direction de synchronisation de Upload et appelle Synchronize. La méthode est appelée deux fois pour effectuer une synchronisation bidirectionnelle entre les réplicas.

SyncFileSystemReplicasOneWay(replica1RootPath, replica2RootPath, null, options);
SyncFileSystemReplicasOneWay(replica2RootPath, replica1RootPath, null, options);
public static void SyncFileSystemReplicasOneWay(
        string sourceReplicaRootPath, string destinationReplicaRootPath,
        FileSyncScopeFilter filter, FileSyncOptions options)
{
    FileSyncProvider sourceProvider = null;
    FileSyncProvider destinationProvider = null;

    try
    {
        // Instantiate source and destination providers, with a null filter (the filter
        // was specified in DetectChangesOnFileSystemReplica()), and options for both.
        sourceProvider = new FileSyncProvider(
            sourceReplicaRootPath, filter, options);
        destinationProvider = new FileSyncProvider(
            destinationReplicaRootPath, filter, options);

        // Register event handlers so that we can write information
        // to the console.
        destinationProvider.AppliedChange +=
            new EventHandler<AppliedChangeEventArgs>(OnAppliedChange);
        destinationProvider.SkippedChange +=
            new EventHandler<SkippedChangeEventArgs>(OnSkippedChange);

        // Use SyncCallbacks for conflicting items.
        SyncCallbacks destinationCallbacks = destinationProvider.DestinationCallbacks;
        destinationCallbacks.ItemConflicting += new EventHandler<ItemConflictingEventArgs>(OnItemConflicting);
        destinationCallbacks.ItemConstraint += new EventHandler<ItemConstraintEventArgs>(OnItemConstraint);

        SyncOrchestrator agent = new SyncOrchestrator();
        agent.LocalProvider = sourceProvider;
        agent.RemoteProvider = destinationProvider;
        agent.Direction = SyncDirectionOrder.Upload; // Upload changes from the source to the destination.

        Console.WriteLine("Synchronizing changes to replica: " +
            destinationProvider.RootDirectoryPath);
        agent.Synchronize();
    }
    finally
    {
        // Release resources.
        if (sourceProvider != null) sourceProvider.Dispose();
        if (destinationProvider != null) destinationProvider.Dispose();
    }
}
SyncFileSystemReplicasOneWay(replica1RootPath, replica2RootPath, Nothing, options)
SyncFileSystemReplicasOneWay(replica2RootPath, replica1RootPath, Nothing, options)
Public Shared Sub SyncFileSystemReplicasOneWay(ByVal sourceReplicaRootPath As String, _
                                               ByVal destinationReplicaRootPath As String, ByVal filter As FileSyncScopeFilter, _
                                               ByVal options As FileSyncOptions)

    Dim sourceProvider As FileSyncProvider = Nothing
    Dim destinationProvider As FileSyncProvider = Nothing

    Try
        ' Instantiate source and destination providers, with a null filter (the filter
        ' was specified in DetectChangesOnFileSystemReplica()), and options for both.
        sourceProvider = New FileSyncProvider(sourceReplicaRootPath, filter, options)
        destinationProvider = New FileSyncProvider(destinationReplicaRootPath, filter, options)

        ' Register event handlers so that we can write information 
        ' to the console. 
        AddHandler destinationProvider.AppliedChange, AddressOf OnAppliedChange
        AddHandler destinationProvider.SkippedChange, AddressOf OnSkippedChange

        ' Use SyncCallbacks for conflicting items.
        Dim destinationCallbacks As SyncCallbacks = destinationProvider.DestinationCallbacks
        AddHandler destinationCallbacks.ItemConflicting, AddressOf OnItemConflicting
        AddHandler destinationCallbacks.ItemConstraint, AddressOf OnItemConstraint

        Dim agent As New SyncOrchestrator()
        agent.LocalProvider = sourceProvider
        agent.RemoteProvider = destinationProvider
        agent.Direction = SyncDirectionOrder.Upload
        ' Upload changes from the source to the destination. 
        Console.WriteLine("Synchronizing changes to replica: " & destinationProvider.RootDirectoryPath)
        agent.Synchronize()
    Finally
        ' Release resources. 
        If sourceProvider IsNot Nothing Then
            sourceProvider.Dispose()
        End If
        If destinationProvider IsNot Nothing Then
            destinationProvider.Dispose()
        End If
    End Try
End Sub

Exemple de code complet

Le code suivant est le code complet pour cet exemple. Les exemples précédents de cette section proviennent de ce code. Pour exécuter ce code :

  • Créez un projet d'application console, puis ajoutez le code au projet.

  • Ajoutez les références à Microsoft.Synchronzation.dll et Microsoft.Synchronzation.Files.dll.

  • Générez le projet pour créer un fichier exécutable.

  • Exécutez le fichier exécutable à partir de la ligne de commande pour synchroniser les fichiers et sous-répertoires contenus dans les répertoires des deux réplicas : MyExeName.exe \path\to\directoryA \path\to\directoryB.

using System;
using System.IO;
using Microsoft.Synchronization;
using Microsoft.Synchronization.Files;

namespace Microsoft.Samples.Synchronization
{
    class Program
    {
        public static void Main(string[] args)
        {
            if (args.Length < 2 ||
                string.IsNullOrEmpty(args[0]) || string.IsNullOrEmpty(args[1]) ||
                !Directory.Exists(args[0]) || !Directory.Exists(args[1]))
            {
                Console.WriteLine(
                  "Usage: MyExecutableName.exe [valid directory path 1] [valid directory path 2]");
                return;
            }

            string replica1RootPath = args[0];
            string replica2RootPath = args[1];

            try
            {
                // Set options for the synchronization session. In this case, options specify
                // that the application will explicitly call FileSyncProvider.DetectChanges, and
                // that items should be moved to the Recycle Bin instead of being permanently deleted.
                FileSyncOptions options = FileSyncOptions.ExplicitDetectChanges |
                         FileSyncOptions.RecycleDeletedFiles | FileSyncOptions.RecyclePreviousFileOnUpdates | 
                         FileSyncOptions.RecycleConflictLoserFiles;

                // Create a filter that excludes all *.lnk files. The same filter should be used 
                // by both providers.
                FileSyncScopeFilter filter = new FileSyncScopeFilter();
                filter.FileNameExcludes.Add("*.lnk");

                // Explicitly detect changes on both replicas before syncyhronization occurs.
                // This avoids two change detection passes for the bidirectional synchronization 
                // that we will perform.
                DetectChangesOnFileSystemReplica(
                    replica1RootPath, filter, options);
                DetectChangesOnFileSystemReplica(
                    replica2RootPath, filter, options);

                // Synchronize the replicas in both directions. In the first session replica 1 is
                // the source, and in the second session replica 2 is the source. The third parameter
                // (the filter value) is null because the filter is specified in DetectChangesOnFileSystemReplica().
                SyncFileSystemReplicasOneWay(replica1RootPath, replica2RootPath, null, options);
                SyncFileSystemReplicasOneWay(replica2RootPath, replica1RootPath, null, options);
            }
            catch (Exception e)
            {
                Console.WriteLine("\nException from File Sync Provider:\n" + e.ToString());
            }
        }

        // Create a provider, and detect changes on the replica that the provider
        // represents.
        public static void DetectChangesOnFileSystemReplica(
                string replicaRootPath,
                FileSyncScopeFilter filter, FileSyncOptions options)
        {
            FileSyncProvider provider = null;

            try
            {
                provider = new FileSyncProvider(replicaRootPath, filter, options);
                provider.DetectChanges();
            }
            finally
            {
                // Release resources.
                if (provider != null)
                    provider.Dispose();
            }
        }

        public static void SyncFileSystemReplicasOneWay(
                string sourceReplicaRootPath, string destinationReplicaRootPath,
                FileSyncScopeFilter filter, FileSyncOptions options)
        {
            FileSyncProvider sourceProvider = null;
            FileSyncProvider destinationProvider = null;

            try
            {
                // Instantiate source and destination providers, with a null filter (the filter
                // was specified in DetectChangesOnFileSystemReplica()), and options for both.
                sourceProvider = new FileSyncProvider(
                    sourceReplicaRootPath, filter, options);
                destinationProvider = new FileSyncProvider(
                    destinationReplicaRootPath, filter, options);

                // Register event handlers so that we can write information
                // to the console.
                destinationProvider.AppliedChange +=
                    new EventHandler<AppliedChangeEventArgs>(OnAppliedChange);
                destinationProvider.SkippedChange +=
                    new EventHandler<SkippedChangeEventArgs>(OnSkippedChange);

                // Use SyncCallbacks for conflicting items.
                SyncCallbacks destinationCallbacks = destinationProvider.DestinationCallbacks;
                destinationCallbacks.ItemConflicting += new EventHandler<ItemConflictingEventArgs>(OnItemConflicting);
                destinationCallbacks.ItemConstraint += new EventHandler<ItemConstraintEventArgs>(OnItemConstraint);

                SyncOrchestrator agent = new SyncOrchestrator();
                agent.LocalProvider = sourceProvider;
                agent.RemoteProvider = destinationProvider;
                agent.Direction = SyncDirectionOrder.Upload; // Upload changes from the source to the destination.

                Console.WriteLine("Synchronizing changes to replica: " +
                    destinationProvider.RootDirectoryPath);
                agent.Synchronize();
            }
            finally
            {
                // Release resources.
                if (sourceProvider != null) sourceProvider.Dispose();
                if (destinationProvider != null) destinationProvider.Dispose();
            }
        }

        // Provide information about files that were affected by the synchronization session.
        public static void OnAppliedChange(object sender, AppliedChangeEventArgs args)
        {
            switch (args.ChangeType)
            {
                case ChangeType.Create:
                    Console.WriteLine("-- Applied CREATE for file " + args.NewFilePath);
                    break;
                case ChangeType.Delete:
                    Console.WriteLine("-- Applied DELETE for file " + args.OldFilePath);
                    break;
                case ChangeType.Update:
                    Console.WriteLine("-- Applied OVERWRITE for file " + args.OldFilePath);
                    break;
                case ChangeType.Rename:
                    Console.WriteLine("-- Applied RENAME for file " + args.OldFilePath +
                                      " as " + args.NewFilePath);
                    break;
            }
        }

        // Provide error information for any changes that were skipped.
        public static void OnSkippedChange(object sender, SkippedChangeEventArgs args)
        {
            Console.WriteLine("-- Skipped applying " + args.ChangeType.ToString().ToUpper()
                  + " for " + (!string.IsNullOrEmpty(args.CurrentFilePath) ?
                                args.CurrentFilePath : args.NewFilePath) + " due to error");

            if (args.Exception != null)
                Console.WriteLine("   [" + args.Exception.Message + "]");
        }

        // By default, conflicts are resolved in favor of the last writer. In this example,
        // the change from the source in the first session (replica 1), will always
        // win the conflict.
        public static void OnItemConflicting(object sender, ItemConflictingEventArgs args)
        {
            args.SetResolutionAction(ConflictResolutionAction.SourceWins);
            Console.WriteLine("-- Concurrency conflict detected for item " + args.DestinationChange.ItemId.ToString());
        }

        public static void OnItemConstraint(object sender, ItemConstraintEventArgs args)
        {
            args.SetResolutionAction(ConstraintConflictResolutionAction.SourceWins);
            Console.WriteLine("-- Constraint conflict detected for item " + args.DestinationChange.ItemId.ToString());
        }
    }
}

Dans l'exemple Visual Basic, le code définit explicitement l'attribut MTAThread sur la méthode Main(). Le fournisseur de synchronisation de fichiers requiert que les applications utilisent le modèle multithread cloisonné (MTA).

Imports System
Imports System.IO
Imports Microsoft.Synchronization
Imports Microsoft.Synchronization.Files

Namespace Microsoft.Samples.Synchronization

    Class Program

        ' File synchronization provider requires applications to use the multithreaded apartment (MTA) 
        ' threading model. This is specified by using the MTAThread attribute.
        <MTAThreadAttribute()> _
        Public Shared Sub Main(ByVal args As String())
            If args.Length < 2 OrElse String.IsNullOrEmpty(args(0)) OrElse String.IsNullOrEmpty(args(1)) OrElse Not Directory.Exists(args(0)) OrElse Not Directory.Exists(args(1)) Then
                Console.WriteLine("Usage: MyExecutableName.exe [valid directory path 1] [valid directory path 2]")
                Exit Sub
            End If

            Dim replica1RootPath As String = args(0)
            Dim replica2RootPath As String = args(1)

            Try
                ' Set options for the synchronization session. In this case, options specify 
                ' that the application will explicitly call FileSyncProvider.DetectChanges, and 
                ' that items should be moved to the Recycle Bin instead of being permanently deleted. 
                Dim options As FileSyncOptions = _
                    FileSyncOptions.ExplicitDetectChanges Or FileSyncOptions.RecycleDeletedFiles _
                    Or FileSyncOptions.RecyclePreviousFileOnUpdates _
                    Or FileSyncOptions.RecycleConflictLoserFiles

                ' Create a filter that excludes all *.lnk files. The same filter should be used 
                ' by both providers.
                Dim filter As New FileSyncScopeFilter()
                filter.FileNameExcludes.Add("*.lnk")

                ' Explicitly detect changes on both replicas before syncyhronization occurs. 
                ' This avoids two change detection passes for the bidirectional synchronization 
                ' that we will perform. 
                DetectChangesOnFileSystemReplica(replica1RootPath, filter, options)
                DetectChangesOnFileSystemReplica(replica2RootPath, filter, options)

                ' Synchronize the replicas in both directions. In the first session replica 1 is 
                ' the source, and in the second session replica 2 is the source. The third parameter
                ' (the filter value) is null because the filter is specified in DetectChangesOnFileSystemReplica().
                SyncFileSystemReplicasOneWay(replica1RootPath, replica2RootPath, Nothing, options)
                SyncFileSystemReplicasOneWay(replica2RootPath, replica1RootPath, Nothing, options)
            Catch e As Exception
                Console.WriteLine(vbLf & "Exception from File Sync Provider:" & vbLf & e.ToString())
            End Try
        End Sub

        ' Create a provider, and detect changes on the replica that the provider 
        ' represents. 
        Public Shared Sub DetectChangesOnFileSystemReplica(ByVal replicaRootPath As String, ByVal filter As FileSyncScopeFilter, _
                                                           ByVal options As FileSyncOptions)
            Dim provider As FileSyncProvider = Nothing

            Try
                provider = New FileSyncProvider(replicaRootPath, filter, options)
                provider.DetectChanges()
            Finally
                ' Release resources. 
                If provider IsNot Nothing Then
                    provider.Dispose()
                End If
            End Try
        End Sub

        Public Shared Sub SyncFileSystemReplicasOneWay(ByVal sourceReplicaRootPath As String, _
                                                       ByVal destinationReplicaRootPath As String, ByVal filter As FileSyncScopeFilter, _
                                                       ByVal options As FileSyncOptions)

            Dim sourceProvider As FileSyncProvider = Nothing
            Dim destinationProvider As FileSyncProvider = Nothing

            Try
                ' Instantiate source and destination providers, with a null filter (the filter
                ' was specified in DetectChangesOnFileSystemReplica()), and options for both.
                sourceProvider = New FileSyncProvider(sourceReplicaRootPath, filter, options)
                destinationProvider = New FileSyncProvider(destinationReplicaRootPath, filter, options)

                ' Register event handlers so that we can write information 
                ' to the console. 
                AddHandler destinationProvider.AppliedChange, AddressOf OnAppliedChange
                AddHandler destinationProvider.SkippedChange, AddressOf OnSkippedChange

                ' Use SyncCallbacks for conflicting items.
                Dim destinationCallbacks As SyncCallbacks = destinationProvider.DestinationCallbacks
                AddHandler destinationCallbacks.ItemConflicting, AddressOf OnItemConflicting
                AddHandler destinationCallbacks.ItemConstraint, AddressOf OnItemConstraint

                Dim agent As New SyncOrchestrator()
                agent.LocalProvider = sourceProvider
                agent.RemoteProvider = destinationProvider
                agent.Direction = SyncDirectionOrder.Upload
                ' Upload changes from the source to the destination. 
                Console.WriteLine("Synchronizing changes to replica: " & destinationProvider.RootDirectoryPath)
                agent.Synchronize()
            Finally
                ' Release resources. 
                If sourceProvider IsNot Nothing Then
                    sourceProvider.Dispose()
                End If
                If destinationProvider IsNot Nothing Then
                    destinationProvider.Dispose()
                End If
            End Try
        End Sub

        ' Provide information about files that were affected by the synchronization session. 
        Public Shared Sub OnAppliedChange(ByVal sender As Object, ByVal args As AppliedChangeEventArgs)
            Select Case args.ChangeType
                Case ChangeType.Create
                    Console.WriteLine("-- Applied CREATE for file " & args.NewFilePath)
                    Exit Select
                Case ChangeType.Delete
                    Console.WriteLine("-- Applied DELETE for file " & args.OldFilePath)
                    Exit Select
                Case ChangeType.Update
                    Console.WriteLine("-- Applied OVERWRITE for file " & args.OldFilePath)
                    Exit Select
                Case ChangeType.Rename
                    Console.WriteLine(("-- Applied RENAME for file " & args.OldFilePath & " as ") & args.NewFilePath)
                    Exit Select
            End Select
        End Sub

        ' Provide error information for any changes that were skipped. 
        Public Shared Sub OnSkippedChange(ByVal sender As Object, ByVal args As SkippedChangeEventArgs)
            Console.WriteLine(("-- Skipped applying " & args.ChangeType.ToString().ToUpper() & " for ") & (If(Not String.IsNullOrEmpty(args.CurrentFilePath), args.CurrentFilePath, args.NewFilePath)) & " due to error")

            If args.Exception IsNot Nothing Then
                Console.WriteLine(" [" & args.Exception.Message & "]")
            End If
        End Sub

        ' By default, conflicts are resolved in favor of the last writer. In this example, 
        ' the change from the source in the first session (replica 1), will always 
        ' win the conflict. 
        Public Shared Sub OnItemConflicting(ByVal sender As Object, ByVal args As ItemConflictingEventArgs)
            args.SetResolutionAction(ConflictResolutionAction.SourceWins)
            Console.WriteLine("-- Concurrency conflict detected for item " & args.DestinationChange.ItemId.ToString())
        End Sub

        Public Shared Sub OnItemConstraint(ByVal sender As Object, ByVal args As ItemConstraintEventArgs)
            args.SetResolutionAction(ConstraintConflictResolutionAction.SourceWins)
            Console.WriteLine("-- Constraint conflict detected for item " & args.DestinationChange.ItemId.ToString())
        End Sub
    End Class
End Namespace

Voir aussi

Référence

Microsoft.Synchronization.Files

Autres ressources

Synchronisation des fichiers