/// <param name="callback">The callback routine to call on progress</param> public override void DoOperation(IOProgressCallback callback) { if (string.IsNullOrEmpty(FileName) || string.IsNullOrEmpty(TransferDestination)) throw new InvalidOperationException("FileName and TransferDestination cannot be blank or null."); PrepareDirectory(); CopyFileFlags flags = CopyFileFlags.COPY_FILE_ALLOW_DECRYPTED_DESTINATION; if (!this.Overwrite) flags = flags | CopyFileFlags.COPY_FILE_FAIL_IF_EXISTS; FileCopier.Copy(Path.GetFullPath(FileName), Path.GetFullPath(TransferDestination), flags, callback); }
/// <summary> /// Copies the specified file to the specified destination path /// </summary> /// <param name="source">The file to copy</param> /// <param name="destination">The path and file name to copy the file to</param> /// <param name="progressHandler">A <see cref="IOProgressCallback"/> to report progress to</param> /// <param name="flags">A <see cref="CopyFileFlags"/> indicating copy options</param> private static void Copy(string source, string destination, CopyFileFlags flags, IOProgressCallback progressHandler, ref bool cancel) { source = Path.GetFullPath(source); destination = Path.GetFullPath(destination); unsafe { fixed (Boolean* cancelp = &cancel) { CopyProgressRoutine routine = (total, transferred, streamSize, StreamByteTrans, dwStreamNumber, reason, hSourceFile, hDestinationFile, lpData) => { if (progressHandler != null) { return progressHandler(total - transferred, transferred, source, destination); } return IOProgressResult.PROGRESS_CONTINUE; }; if (!CopyFileEx(source, destination, routine, IntPtr.Zero, cancelp, flags)) { HandleCopyExError(source, destination, Marshal.GetLastWin32Error()); } } } }
/// <param name="callback">The callback routine to call on progress</param> public override void DoOperation(IOProgressCallback callback) { if (string.IsNullOrEmpty(FileName) || string.IsNullOrEmpty(TransferDestination)) throw new InvalidOperationException("FileName and TransferDestination cannot be blank or null."); //Moves on the same volume should be so fast we can treat them as deletes or renames, //no progress needed. On other volumes, just fake the move and use the copy system. if (IsSameVolume) { PrepareDirectory(); File.Move(FileName, TransferDestination); } else { base.DoOperation(callback); File.Delete(FileName); } if (DeleteEmptyFolder && Directory.GetFileSystemEntries(Path.GetDirectoryName(FileName)).Length == 0) { Directory.Delete(Path.GetDirectoryName(FileName)); } }
internal static void Copy(string source, string destination, CopyFileFlags flags, IOProgressCallback progressHandler) { bool dummy = false; //Cancel is handled exclusively via progressHandler Copy(source, destination, flags, progressHandler, ref dummy); }
private void ProcessOperation(IOOperation operation) { lock (statLock) bytesPending -= operation.EffectiveFileSize; try { //Copy operations get some special callbacks and tracking OngoingOperation progressOp = operation as OngoingOperation; if (progressOp != null) { IOProgressCallback copyCall = new IOProgressCallback((pending, transferred, sourceFile, destinationFile) => { OperationProgressDetails details = new OperationProgressDetails(operation, transferred, pending); activeOperations[operation] = details; OnProgress(details); //TODO: potentially add in-file pause to this? Right now we only support one in-file operation: cancel. if (State == OperationState.Terminated) return IOProgressResult.PROGRESS_CANCEL; else return IOProgressResult.PROGRESS_CONTINUE; }); progressOp.DoOperation(copyCall); } else { operation.DoOperation(); } } catch (Exception e) //We're catching everything (*gasp!*) so we can bubble it up without blowing up stacks of threads. { OnProgress(new OperationProgressDetails(operation, e)); } finally { lock(statLock) { if (operation.EffectiveFileSize > 0 && activeOperations.ContainsKey(operation)) activeOperations.Remove(operation); bytesProcessed += operation.EffectiveFileSize; operationsProcessed += 1; } //Notify the caller that the operation has completed OnProgress(new OperationProgressDetails(operation, true)); } }
public abstract void DoOperation(IOProgressCallback callback);