Procedura: sincronizzare file utilizzando il codice gestito

In questo argomento viene illustrato come utilizzare un linguaggio gestito, ad esempio C# o Visual Basic, per creare un'applicazione che sincronizzi file e sottocartelle mediante il provider di sincronizzazione di Sync Framework.

Gli esempi contenuti in questo argomento riguardano i tipi seguenti di Sync Framework:

Informazioni sulla sincronizzazione di file

Sync Framework implementa un provider di sincronizzazione che può essere utilizzato per sincronizzare file e sottocartelle presenti in una cartella di un file system. Questo provider espone diverse impostazioni configurabili per fornire un grado di controllo più preciso sulla modalità di esecuzione della sincronizzazione e sugli elementi da sincronizzare. Per sincronizzare i file tra due cartelle, un'applicazione completa i passaggi di base seguenti:

  1. Crea un oggetto FileSyncProvider per rappresentare ogni cartella.

  2. Passa i due provider a un oggetto SyncOrchestrator e ne specifica uno come provider di origine e l'altro come provider di destinazione.

  3. Chiama Synchronize per avviare la sessione di sincronizzazione.

Per ulteriori informazioni sulla sincronizzazione di file, vedere Sincronizzazione di file.

Esempio

Il codice di esempio in questa sezione deriva da un'applicazione console che sincronizza due directory, incluse le sottodirectory e i file in esse contenuti. Nel codice di esempio vengono illustrate le attività seguenti:

  • Impostazione delle opzioni di sincronizzazione.

  • Esecuzione esplicita del rilevamento delle modifiche per una replica.

  • Configurazione di un filtro per il controllo degli elementi da includere nella sincronizzazione.

  • Gestione dei conflitti che possono verificarsi durante la sincronizzazione.

  • Modalità di sincronizzazione di due repliche.

Dopo questi esempi di codice, viene illustrato il codice completo per l'applicazione in modo che sia possibile compilarla ed eseguirla.

Impostazione delle opzioni di sincronizzazione

L'oggetto FileSyncOptions consente di impostare diverse opzioni per la sincronizzazione dei file, tra cui il rilevamento delle modifiche, l'eventuale eliminazione di elementi durante la sincronizzazione o il loro spostamento nel Cestino. Nell'esempio di codice seguente vengono impostate quattro opzioni, tre delle quali correlate alle eliminazioni di elementi. Con l'opzione ExplicitDetectChanges, Sync Framework non eseguirà il rilevamento delle modifiche, a meno che l'applicazione non chiami in modo esplicito DetectChanges. Per un'ulteriore spiegazione, vedere la sezione successiva "Esecuzione del rilevamento delle modifiche".

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

Esecuzione del rilevamento delle modifiche

Per impostazione predefinita, Sync Framework esegue il rilevamento delle modifiche in entrambe le repliche ogni volta che viene chiamato Synchronize. Tramite il rilevamento delle modifiche, Sync Framework determina quali elementi devono essere inviati dall'origine alla destinazione e quali causano conflitti. Specificando ExplicitDetectChanges, è possibile stabilire quando eseguire il rilevamento delle modifiche. Nell'esempio di codice seguente il rilevamento delle modifiche per ogni replica viene chiamato prima di qualsiasi chiamata a Synchronize. In questo esempio si intende illustrare DetectChanges, ma si ha il vantaggio di ottenere un solo passaggio di rilevamento delle modifiche anziché i due che si otterrebbero eseguendo in seguito una sincronizzazione bidirezionale nell'applicazione.

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

Impostazione di un filtro statico

I filtri statici possono essere impostati per escludere i file in base al nome (inclusi i nomi contenenti caratteri jolly) e all'attributo. I filtri statici possono inoltre essere impostati per escludere il contenuto di intere sottocartelle. È anche possibile specificare un elenco esplicito di nomi di file da includere (inclusi i nomi contenenti caratteri jolly). Per essere incluso nell'ambito, un file o una cartella deve soddisfare i requisiti di tutti i filtri. Ad esempio, se si escludono dall'ambito tutti i file con estensione txt e si specifica MyFile.txt nell'elenco di file da includere in modo esplicito nell'ambito, tale file verrà escluso a causa dell'estensione txt.

Nell'esempio di codice seguente viene utilizzato l'oggetto FileSyncScopeFilter per creare un filtro che esclude tutti i file *.lnk. Un filtro non ha alcuna relazione con il relativo provider di creazione. Per connettere un filtro a un provider, passarlo a uno dei costruttori per FileSyncProvider oppure impostare la proprietà ScopeFilter. Nell'applicazione di esempio questa operazione viene eseguita nel metodo DetectChangesOnFileSystemReplica() perché il filtro riguarda unicamente il rilevamento delle modifiche. Poiché il filtro è indipendente dal provider, è necessario creare un solo filtro per sessione di sincronizzazione. I provider non devono utilizzare filtri diversi, perché questo potrebbe impedire la convergenza dei dati.

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

Oltre ai filtri statici, è inoltre possibile escludere file durante la sincronizzazione gestendo un evento generato dal provider. Per ulteriori informazioni, vedere Controllo dei file sincronizzati.

Gestione dei conflitti

Sync Framework rileva e risolve i conflitti di concorrenza e i conflitti di vincoli per file e cartelle. Si verifica un conflitto di concorrenza quando lo stesso elemento viene modificato in entrambe le repliche dopo l'ultima sessione di sincronizzazione tra le due repliche. Si verifica un conflitto di vincoli se un file o una cartella con lo stesso nome viene aggiunta a entrambe le repliche. I conflitti vengono risolti conservando il file o la cartella con la modifica più recente ed eliminando (o spostando) il file o la cartella con la modifica meno recente. Per i file, si ha anche la possibilità di specificare che l'origine o la destinazione deve prevalere nel conflitto, indipendentemente dalla modifica che si verificata per prima. Nell'esempio di codice seguente vengono registrati gestori eventi per gli eventi ItemConflicting e ItemConstraint disponibili attraverso l'oggetto SyncCallbacks. I metodi chiamati risolvono tutti i conflitti in favore dell'origine e scrivono le informazioni nella 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

Sincronizzazione di due repliche

Dopo l'impostazione delle opzioni e dei filtri, l'applicazione sincronizza le due repliche creano un'istanza di SyncOrchestrator e chiamando il metodo Synchronize. Nell'esempio di codice seguente viene specificato il provider per ogni replica, vengono impostate le opzioni, vengono registrati i gestori eventi, viene specificata una direzione di sincronizzazione di Uploade viene chiamato Synchronize. Il metodo viene chiamato due volte per eseguire la sincronizzazione bidirezionale tra le repliche.

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

Esempio di codice completo

Il codice seguente è il codice completo per questo esempio. Gli esempi precedenti di questa sezione sono stati ricavati da questo codice. Per eseguire questo codice:

  • Creare un progetto di applicazione console e aggiungere il codice al progetto.

  • Aggiungere riferimenti a Microsoft.Synchronzation.dll e Microsoft.Synchronzation.Files.dll.

  • Compilare il progetto per creare un eseguibile.

  • Eseguire l'eseguibile dalla riga di comando per sincronizzare i file e le sottodirectory di due directory della replica: 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());
        }
    }
}

Nell'esempio Visual Basic il codice imposta in modo esplicito l'attributo MTAThread sul metodo Main(). Il provider di sincronizzazione dei file richiede che le applicazioni utilizzino il modello di threading dell'apartment (MTA) a thread multipli.

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

Vedere anche

Riferimento

Microsoft.Synchronization.Files

Concetti

Sincronizzazione di file