using Microsoft.WindowsAPICodePack.Taskbar; using System; using System.IO; using System.Threading; using System.Windows.Forms; namespace StrangeFileCopy { public partial class MainForm : Form { private string _status = "Ready"; private int _bufProgress; private int _reOpenProgress; private int _totalProgress; private bool _pause; private bool _error; public MainForm() => InitializeComponent(); private void FireButton_Click(object sender, EventArgs e) { var srcPath = FromTextBox.Text; var dstPath = ToTextBox.Text; if (string.IsNullOrWhiteSpace(srcPath) || string.IsNullOrWhiteSpace(dstPath)) { MessageBox.Show("Before start,fill `File From' and `To Folder'"); return; } var blkSize = MaxCheckBox.Checked ? 2147483591 : (int)BufSizeUpDown.Value * 1024 * 1024; var reOpenTimes = (int)Math.Ceiling(ReOpenSizeUnDown.Value * 1024 * 1024 * 1024 / blkSize); var flush = FlushCheckBox.Checked; FireButton.Enabled = false; ConfigGroupBox.Enabled = false; new Thread(() => { FileStream src = null; FileStream dst = null; try { _status = "Opening Source"; src = File.OpenRead(srcPath); var srcLen = src.Length; _status = "Pre allocating Dest - Opening"; dst = File.OpenWrite(dstPath); _status = "Pre allocating Dest - Seeking"; dst.Position = src.Length - 1; _status = "Pre allocating Dest - Writing"; dst.WriteByte(0); _status = "Pre allocating Dest - Flushing"; dst.Flush(true); _status = "Pre allocating Dest - Closing"; dst.Close(); long pos = 0; var buf = new byte[blkSize]; while (pos < srcLen) { _status = "Opening Dest"; dst = File.OpenWrite(dstPath); dst.Position = pos; for (var i = 0; i < reOpenTimes; i++) { _status = "Reading Source"; var bi = 0; var read = 0; do { read = src.Read(buf, bi, blkSize - read); bi += read; _bufProgress = (int)(100 * (float)bi / blkSize); } while (read > 0 && bi < blkSize); _status = "Writing Dst"; dst.Write(buf, 0, bi); _status = "Flushing Dst"; if (flush) dst.Flush(true); _reOpenProgress = (int)(100 * (float)i / reOpenTimes); _totalProgress = (int)(100 * (float)src.Position / srcLen); if (_pause) { _status = "Paused"; while (_pause) { Thread.Sleep(250); } } if (src.Position == srcLen) break; } pos = src.Position; _status = "Closing Dst"; dst.Close(); } _status = "Done"; } catch (Exception exception) { _status = $"Error:{exception.Message}"; _error = true; } finally { src?.Close(); try { dst?.Close(); } catch { //ignore } } }).Start(); } private void UiUpdateTimer_Tick(object sender, EventArgs e) { CurrentOperationLabel.Text = _status; BufProgressBar.Value = _bufProgress; ReOpenProgressBar.Value = _reOpenProgress; TotalProgressBar.Value = _totalProgress; if (_error) { TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.Error); } else { TaskbarManager.Instance.SetProgressState(_pause ? TaskbarProgressBarState.Paused : TaskbarProgressBarState.Normal); TaskbarManager.Instance.SetProgressValue(_totalProgress, 100); } } private void FromTextBox_DragEnter(object sender, DragEventArgs e) { string[] files; e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) && (files = (string[])e.Data.GetData(DataFormats.FileDrop)).Length == 1 && File.Exists(files[0]) ? DragDropEffects.Copy : DragDropEffects.None; } private void FromTextBox_DragDrop(object sender, DragEventArgs e) => FromTextBox.Text = ((string[])e.Data.GetData(DataFormats.FileDrop))[0]; private void ToTextBox_DragEnter(object sender, DragEventArgs e) { string[] files; e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) && (files = (string[])e.Data.GetData(DataFormats.FileDrop)).Length == 1 && Directory.Exists(files[0]) ? DragDropEffects.Copy : DragDropEffects.None; } private void ToTextBox_DragDrop(object sender, DragEventArgs e) { var to = ((string[])e.Data.GetData(DataFormats.FileDrop))[0]; new Thread(() => { Invoke(new Action(delegate { if (string.IsNullOrWhiteSpace(FromTextBox.Text)) { MessageBox.Show("Fill `File from' first!"); return; } var filename = Path.GetFileName(FromTextBox.Text); var dest = Path.Combine(to, filename); if (File.Exists(dest)) { if (DialogResult.Yes == MessageBox.Show("Target file exist,override it?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)) { ToTextBox.Text = dest; } else { ToTextBox.Clear(); } } else { ToTextBox.Text = dest; } })); }).Start(); } private void MaxCheckBox_CheckedChanged(object sender, EventArgs e) => BufSizeUpDown.Enabled = !MaxCheckBox.Checked; private void PauseCheckBox_CheckedChanged(object sender, EventArgs e) => _pause = PauseCheckBox.Checked; } }