I recently tried to implement SynchronizeDirectories to a new wpf app I'm building and I'm facing weird issues with events that are acting in a strange way.
The synchronization is working properly in both ways, but the progressbar is not updated during the synchronization itself, only at the end of the process. In short terms, my code is going to eventHandlers but not updating the window itself. Any ideas on that ?
<Window x:Class="MyApp.SynchronizationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Mod synchronization" Width="500" WindowStyle="ToolWindow" SizeToContent="Height" WindowStartupLocation="CenterOwner" ResizeMode="NoResize" ShowInTaskbar="False" ContentRendered="Window_ContentRendered">
<DockPanel>
<StackPanel DockPanel.Dock="Bottom">
<StatusBar>
<StatusBarItem>
<TextBlock Name="statusText" />
</StatusBarItem>
</StatusBar>
</StackPanel>
<StackPanel Margin="0,0,0,5">
<Label Content="Current File" />
<Label Name="fileName" Content="" BorderThickness="0" Margin="30,0,10,0" />
<StackPanel Margin="50,0">
<StackPanel Orientation="Horizontal">
<Label Content="File progress :" />
<Label Name="filePercentage" Content="0%" />
</StackPanel>
<ProgressBar Name="fileProgress" Height="15" Foreground="#FF01D328" />
<StackPanel Orientation="Horizontal">
<Label Content="Overall progress :" />
<Label Name="overallPercentage" Content="0%" />
</StackPanel>
<ProgressBar Name="overallProgress" Height="15" Foreground="#FF0160D3" />
</StackPanel>
</StackPanel>
</DockPanel>
</Window>
using MyApp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows;
using WinSCP;
using System.Linq;
namespace MyApp
{
/// <summary>
/// Interaction logic for SynchronizationWindow.xaml
/// </summary>
public partial class SynchronizationWindow : Window
{
private string _lastFileProcessed;
private int _countFilesToSynchronize;
private int _countFilesProcessed;
private Action _selectedAction;
public enum Action
{
DOWNLOAD,
UPLOAD
}
public SynchronizationWindow(Action selectedAction)
{
InitializeComponent();
ResetComponents();
_selectedAction = selectedAction;
}
private void ResetComponents()
{
_countFilesToSynchronize = 0;
_countFilesProcessed = 0;
statusText.Text = null;
fileName.Content = null;
filePercentage.Content = "0%";
fileProgress.Value = 0;
overallPercentage.Content = "0%";
overallProgress.Value = 0;
}
private void SynchronizeToRemote()
{
try
{
// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Sftp,
HostName = Settings.Default.RepositoryUrl,
UserName = Settings.Default.RepositoryName,
Password = Settings.Default.RepositoryPassword,
SshPrivateKeyPath = Settings.Default.RepositoryPrivateKeyPath,
PrivateKeyPassphrase = Settings.Default.RepositoryPrivateKeyPassphrase,
GiveUpSecurityAndAcceptAnySshHostKey = true
};
using (Session session = new Session())
{
// Will continuously report progress of synchronization
session.FileTransferred += FileTransferred;
// Will continuously report progress of transfer
session.FileTransferProgress += SessionFileTransferProgress;
// Connect
session.Open(sessionOptions);
string localPath = Path.Combine("C:\\test");
string remotePath = Path.Combine(Settings.Default.RepositoryStoragePath, "test");
if (!session.FileExists(remotePath))
{
session.CreateDirectory(remotePath);
}
HashSet<string> filesToSynchronize = new HashSet<string>(Directory.GetFiles(localPath, "*.*", SearchOption.AllDirectories).ToList());
_countFilesToSynchronize = filesToSynchronize.Count;
SynchronizationResult synchronizationResult;
synchronizationResult =
session.SynchronizeDirectories(SynchronizationMode.Remote, localPath, remotePath, true);
// Throw on any error
synchronizationResult.Check();
StringBuilder failedFiles = new StringBuilder();
foreach (TransferEventArgs failedFile in synchronizationResult.Failures)
{
failedFiles.AppendLine(string.Format("{0}", failedFile.FileName));
}
if (failedFiles.Length > 0)
{
MessageBox.Show(failedFiles.ToString(), "Error uploading files.");
}
if (synchronizationResult.IsSuccess)
{
overallPercentage.Content = string.Format("{0:P0}", 1);
overallProgress.Value = 100;
statusText.Text = "Operation succeeded.";
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
private void SynchronizeToLocal()
{
try
{
// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Sftp,
HostName = Settings.Default.RepositoryUrl,
UserName = Settings.Default.RepositoryName,
Password = Settings.Default.RepositoryPassword,
SshPrivateKeyPath = Settings.Default.RepositoryPrivateKeyPath,
PrivateKeyPassphrase = Settings.Default.RepositoryPrivateKeyPassphrase,
GiveUpSecurityAndAcceptAnySshHostKey = true
};
using (Session session = new Session())
{
// Will continuously report progress of synchronization
session.FileTransferred += FileTransferred;
// Will continuously report progress of transfer
session.FileTransferProgress += SessionFileTransferProgress;
// Connect
session.Open(sessionOptions);
string localPath = Path.Combine("C:\\test");
string remotePath = Path.Combine(Settings.Default.RepositoryStoragePath, "test");
if (!session.FileExists(remotePath))
{
MessageBox.Show(string.Format("The mod [{0}] doesn't exist in the remote repository [{1}].", Mod.Name, Settings.Default.RepositoryStoragePath));
return;
}
if (!Directory.Exists(localPath))
{
Directory.CreateDirectory(localPath);
}
RemoteDirectoryInfo remoteDirectoryInfo = session.ListDirectory(remotePath);
_countFilesToSynchronize = remoteDirectoryInfo.Files.Count;
SynchronizationResult synchronizationResult;
synchronizationResult =
session.SynchronizeDirectories(SynchronizationMode.Local, localPath, remotePath, true);
// Throw on any error
synchronizationResult.Check();
StringBuilder failedFiles = new StringBuilder();
foreach (TransferEventArgs failedFile in synchronizationResult.Failures)
{
failedFiles.AppendLine(string.Format("{0}", failedFile.FileName));
}
if (failedFiles.Length > 0)
{
MessageBox.Show(failedFiles.ToString(), "Error downloading files.");
}
if (synchronizationResult.IsSuccess)
{
overallPercentage.Content = string.Format("{0:P0}", 1);
overallProgress.Value = 100;
statusText.Text = "Operation succeeded.";
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex);
}
}
private void FileTransferred(object sender, TransferEventArgs e)
{
string returnMessage = string.Empty;
if (e.Error == null)
{
returnMessage = $"Upload of {e.FileName} succeeded";
}
else
{
returnMessage = $"Upload of {e.FileName} failed: {e.Error}";
}
if (e.Chmod != null)
{
if (e.Chmod.Error == null)
{
returnMessage = $"Permissions of {e.Chmod.FileName} set to {e.Chmod.FilePermissions}";
}
else
{
returnMessage = $"Setting permissions of {e.Chmod.FileName} failed: {e.Chmod.Error}";
}
}
else
{
returnMessage = $"Permissions of {e.Destination} kept with their defaults";
}
if (e.Touch != null)
{
if (e.Touch.Error == null)
{
returnMessage = string.Format("Timestamp of {0} set to {1}", e.Touch.FileName, e.Touch.LastWriteTime);
}
else
{
returnMessage = string.Format("Setting timestamp of {0} failed: {1}", e.Touch.FileName, e.Touch.Error);
}
}
else
{
// This should never happen during "local to remote" synchronization
returnMessage = string.Format("Timestamp of {0} kept with its default (current time)", e.Destination);
}
Console.WriteLine(returnMessage);
statusText.Text = returnMessage;
UpdateOverallProgress();
}
private void UpdateOverallProgress()
{
_countFilesProcessed++;
double currentOverallPercentage = (double)_countFilesProcessed / _countFilesToSynchronize;
overallPercentage.Content = string.Format("{0:P0}", currentOverallPercentage);
overallProgress.Value = currentOverallPercentage * 100;
}
private void SessionFileTransferProgress(object sender, FileTransferProgressEventArgs e)
{
// New line for every new file
if (_lastFileProcessed != null && _lastFileProcessed != e.FileName)
{
fileName.Content = String.Format("File [{0}] processed.", e.FileName);
}
// Print transfer progress
string percentage = String.Format("{0:P1}", e.FileProgress);
filePercentage.Content = percentage;
fileProgress.Value = e.FileProgress * 100;
// Remember a name of the last file reported
_lastFileProcessed = e.FileName;
}
private void Window_ContentRendered(object sender, EventArgs e)
{
switch (_selectedAction)
{
case Action.DOWNLOAD:
SynchronizeToLocal();
break;
case Action.UPLOAD:
SynchronizeToRemote();
break;
}
}
}
}