private async void syncButton_Click(object sender, RoutedEventArgs e) { if (wtoken == null) { if (!validateForms()) { return; } // closing open log windows foreach (Window w in System.Windows.Application.Current.Windows) { LiveStreamWindow lsw = w as LiveStreamWindow; if (lsw == null) { continue; } lsw.Close(); } startRunningAnimationAndLockForms(); try { RoboCopyCommand r = new RoboCopyCommand(); r.Source = srcPath.Text; r.Destination = destPath.Text; r.LogFile = logFilePath.Text; // mirror mode r.CopyMirror = mirrorCopy.IsChecked.Value; // copy flags r.CopyFlags = 0; if (copyOptionData.IsChecked.Value) { r.CopyFlags = r.CopyFlags | RoboCopyCopyFlags.Data; } if (copyOptionAttr.IsChecked.Value) { r.CopyFlags = r.CopyFlags | RoboCopyCopyFlags.Attributes; } if (copyOptionTime.IsChecked.Value) { r.CopyFlags = r.CopyFlags | RoboCopyCopyFlags.Timestamps; } if (copyOptionAcl.IsChecked.Value) { r.CopyFlags = r.CopyFlags | RoboCopyCopyFlags.Acls; } if (copyOptionOwner.IsChecked.Value) { r.CopyFlags = r.CopyFlags | RoboCopyCopyFlags.OwnerInfo; } if (copyOptionAudit.IsChecked.Value) { r.CopyFlags = r.CopyFlags | RoboCopyCopyFlags.AuditingInfo; } // retries try { r.CopyRetries = int.Parse(retryNumber.Text); } catch (Exception ex) { throw new Exception("Number of retries is not a valid number:\n" + ex.Message); } try { r.CopyRetrySleepSecs = int.Parse(retryWaitSec.Text); } catch (Exception ex) { throw new Exception("Wait time (in s) is not a valid number:\n" + ex.Message); } // restart mode r.CopyRestartMode = retryRestart.IsChecked.Value; LiveStreamWindow lsw = null; // do we have to open a live stream window? if (liveStreamData.IsChecked.Value) { lsw = new LiveStreamWindow("Running command: " + r.RoboCopyExecPath + " " + r.getRobocopyArguments() + "\n"); if (logFilePath.Text == null || logFilePath.Text == "") { lsw.AppendOutput("Info: No log file has been specified. It is recommended to use a log file!\n"); } r.DisableStandardDataResult = true; r.OutputDataReceived += (s) => lsw.AppendOutput(s); r.ErrorDataReceived += (s) => lsw.AppendOutput(s); r.FilePercentageUpdate += (d) => lsw.UpdateProgressBar(d); } else { r.DisableStandardDataResult = true; // uses less memory, since we will not show any debug window } RoboCopyCommandResult t = await r.Run(); if (liveStreamData.IsChecked.Value && t.ReturnCode > 0) { #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed // background task to ensure, that the Error Message gets appended to the end (Without this, this message will appear in the beginning) Task.Run(async() => { await Task.Delay(100); if (t.ReturnCode > 4) { lsw.AppendOutput("\n" + "RoboCopy failed with return code: " + t.ReturnCode + "\n(" + t.ReturnCodeFlags + ")\n"); } else { lsw.AppendOutput("\n" + "RoboCopy finished with return code: " + t.ReturnCode + "\n(" + t.ReturnCodeFlags + ")\n"); } }); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } if (t.ReturnCode >= 4) { throw new Exception("RoboCopy failed with return code: " + t.ReturnCode + "\n(" + t.ReturnCodeFlags + ")"); } if (liveStreamData.IsChecked.Value) { #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed // background task to ensure, that the ProgressBar gets updated to 100 percent (Without this, the running update from the previous job overrides it) Task.Run(async() => { await Task.Delay(100); lsw.UpdateProgressBar(100); }); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message, "RoboCopy Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation, System.Windows.Forms.MessageBoxDefaultButton.Button1); } finally { //await Task.Delay(4000); // Debug - to see the animation stopRunningAnimationAndUnlockForms(); } } /*else * { * if (!wtoken.IsCancellationRequested) * { * setAllFormsEnabled(true); * * wtoken.Cancel(); * // late disposal * Task.Run(() => * { * Task.Delay(400).Wait(); * this.Dispatcher.Invoke(() => * { * wtoken.Dispose(); * wtoken = null; * task = null; * }); * }); * } * }*/ }
public Task <RoboCopyCommandResult> Run(CancellationToken cancellationToken = default(CancellationToken)) { lastFilePercentageUpdate = DateTime.Now.AddHours(-1); lastFilePercentageValue = 0; RoboCopyCommandResult result = new RoboCopyCommandResult(); TaskCompletionSource <RoboCopyCommandResult> taskSource = new TaskCompletionSource <RoboCopyCommandResult>(); try { Process process = new Process(); process.StartInfo = new ProcessStartInfo() { CreateNoWindow = true, UseShellExecute = false, RedirectStandardInput = true, RedirectStandardError = true, RedirectStandardOutput = true, FileName = this.RoboCopyExecPath, Arguments = getRobocopyArguments() }; process.EnableRaisingEvents = true; process.Exited += (sender, args) => { lazyUpdateFilePercentage(100); result.ReturnCode = process.ExitCode; process.Dispose(); taskSource.TrySetResult(result); }; if (cancellationToken != default(CancellationToken)) { cancellationToken.Register(() => { lazyUpdateFilePercentage(0); try { process.Kill(); } catch { } process.Dispose(); taskSource.SetCanceled(); }); } Regex perecentageRegex = new Regex(@"^\s*(?<percent>\d{1,3}(.\d+)?)%\s*$"); if (DisableStandardDataResult) { result.StandardOutput = null; result.StandardError = null; process.OutputDataReceived += (sender, e) => { if (e.Data == null) { return; } Match m = perecentageRegex.Match(e.Data); if (m.Success) { if (FilePercentageUpdate != null) { lazyUpdateFilePercentage(Double.Parse(m.Groups["percent"].Value, new CultureInfo("en-US").NumberFormat)); } return; } else { lazyUpdateFilePercentage(0); } if (OutputDataReceived == null) { return; } OutputDataReceived.Invoke(e.Data + "\n"); }; process.ErrorDataReceived += (sender, e) => { if (e.Data == null) { return; } if (ErrorDataReceived == null) { return; } ErrorDataReceived.Invoke(e.Data + "\n"); }; } else { result.StandardOutput = ""; result.StandardError = ""; process.OutputDataReceived += (sender, e) => { if (e.Data == null) { return; } Match m = perecentageRegex.Match(e.Data); if (m.Success) { if (FilePercentageUpdate != null) { lazyUpdateFilePercentage(Convert.ToDouble(m.Groups["percent"])); } return; } else { lazyUpdateFilePercentage(0); } result.StandardOutput += e.Data + "\n"; if (OutputDataReceived == null) { return; } OutputDataReceived.Invoke(e.Data + "\n"); }; process.ErrorDataReceived += (sender, e) => { if (e.Data == null) { return; } result.StandardError += e.Data + "\n"; if (ErrorDataReceived == null) { return; } ErrorDataReceived.Invoke(e.Data + "\n"); }; } process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); ProcessId = process.Id; } catch (Exception e) { taskSource.TrySetException(e); } return(taskSource.Task); }