using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Runtime.CompilerServices; namespace RoboSharp { /// /// Source, Destination, and options for how to move or copy files. /// /// /// /// public class CopyOptions : ICloneable { #region Constructors /// /// Create new CopyOptions with Default Settings /// public CopyOptions() { } /// /// Create a new CopyOptions object with the provided settings /// /// /// /// public CopyOptions(string source, string destination, CopyActionFlags flags) { this.Source = source ?? string.Empty; this.Destination = destination ?? string.Empty; this.ApplyActionFlags(flags); } /// /// Clone a CopyOptions Object /// /// CopyOptions object to clone /// Specify a new source if desired. If left as null, will use Source from /// Specify a new source if desired. If left as null, will use Destination from public CopyOptions(CopyOptions copyOptions, string NewSource = null, string NewDestination = null) { Source = NewSource ?? copyOptions.Source; Destination = NewDestination ?? copyOptions.Destination; AddAttributes = copyOptions.AddAttributes; CheckPerFile = copyOptions.CheckPerFile; CopyAll = copyOptions.CopyAll; CopyFilesWithSecurity = copyOptions.CopyFilesWithSecurity; CopyFlags = copyOptions.CopyFlags; CopySubdirectories = copyOptions.CopySubdirectories; CopySubdirectoriesIncludingEmpty = copyOptions.CopySubdirectoriesIncludingEmpty; CopySymbolicLink = copyOptions.CopySymbolicLink; CreateDirectoryAndFileTree = copyOptions.CreateDirectoryAndFileTree; Depth = copyOptions.Depth; DirectoryCopyFlags = copyOptions.DirectoryCopyFlags; DoNotCopyDirectoryInfo = copyOptions.DoNotCopyDirectoryInfo; DoNotUseWindowsCopyOffload = copyOptions.DoNotUseWindowsCopyOffload; EnableBackupMode = copyOptions.EnableBackupMode; EnableEfsRawMode = copyOptions.EnableEfsRawMode; EnableRestartMode = copyOptions.EnableRestartMode; EnableRestartModeWithBackupFallback = copyOptions.EnableRestartModeWithBackupFallback; FatFiles = copyOptions.FatFiles; FileFilter = copyOptions.FileFilter; FixFileSecurityOnAllFiles = copyOptions.FixFileSecurityOnAllFiles; FixFileTimesOnAllFiles = copyOptions.FixFileTimesOnAllFiles; InterPacketGap = copyOptions.InterPacketGap; Mirror = copyOptions.Mirror; MonitorSourceChangesLimit = copyOptions.MonitorSourceChangesLimit; MonitorSourceTimeLimit = copyOptions.MonitorSourceTimeLimit; MoveFiles = copyOptions.MoveFiles; MoveFilesAndDirectories = copyOptions.MoveFilesAndDirectories; MultiThreadedCopiesCount = copyOptions.MultiThreadedCopiesCount; Purge = copyOptions.Purge; RemoveAttributes = copyOptions.RemoveAttributes; RemoveFileInformation = copyOptions.RemoveFileInformation; RunHours = copyOptions.RunHours; TurnLongPathSupportOff = copyOptions.TurnLongPathSupportOff; UseUnbufferedIo = copyOptions.UseUnbufferedIo; } /// public CopyOptions Clone(string NewSource = null, string NewDestination = null) => new CopyOptions(this, NewSource, NewDestination); object ICloneable.Clone() => Clone(); #endregion #region Option Constants internal const string COPY_SUBDIRECTORIES = "/S "; internal const string COPY_SUBDIRECTORIES_INCLUDING_EMPTY = "/E "; internal const string DEPTH = "/LEV:{0} "; internal const string ENABLE_RESTART_MODE = "/Z "; internal const string ENABLE_BACKUP_MODE = "/B "; internal const string ENABLE_RESTART_MODE_WITH_BACKUP_FALLBACK = "/ZB "; internal const string USE_UNBUFFERED_IO = "/J "; internal const string ENABLE_EFSRAW_MODE = "/EFSRAW "; internal const string COPY_FLAGS = "/COPY:{0} "; internal const string COPY_FILES_WITH_SECURITY = "/SEC "; internal const string COPY_ALL = "/COPYALL "; internal const string REMOVE_FILE_INFORMATION = "/NOCOPY "; internal const string FIX_FILE_SECURITY_ON_ALL_FILES = "/SECFIX "; internal const string FIX_FILE_TIMES_ON_ALL_FILES = "/TIMFIX "; internal const string PURGE = "/PURGE "; internal const string MIRROR = "/MIR "; internal const string MOVE_FILES = "/MOV "; internal const string MOVE_FILES_AND_DIRECTORIES = "/MOVE "; internal const string ADD_ATTRIBUTES = "/A+:{0} "; internal const string REMOVE_ATTRIBUTES = "/A-:{0} "; internal const string CREATE_DIRECTORY_AND_FILE_TREE = "/CREATE "; internal const string FAT_FILES = "/FAT "; internal const string TURN_LONG_PATH_SUPPORT_OFF = "/256 "; internal const string MONITOR_SOURCE_CHANGES_LIMIT = "/MON:{0} "; internal const string MONITOR_SOURCE_TIME_LIMIT = "/MOT:{0} "; internal const string RUN_HOURS = "/RH:{0} "; internal const string CHECK_PER_FILE = "/PF "; internal const string INTER_PACKET_GAP = "/IPG:{0} "; internal const string COPY_SYMBOLIC_LINK = "/SL "; internal const string MULTITHREADED_COPIES_COUNT = "/MT:{0} "; internal const string DIRECTORY_COPY_FLAGS = "/DCOPY:{0} "; internal const string DO_NOT_COPY_DIRECTORY_INFO = "/NODCOPY "; internal const string DO_NOT_USE_WINDOWS_COPY_OFFLOAD = "/NOOFFLOAD "; #endregion Option Constants #region Option Defaults /// /// The Default File Filter used that will allow copying of all files /// public const string DefaultFileFilter = "*.*" ; private IEnumerable fileFilter = new[] { DefaultFileFilter }; private string copyFlags = "DAT"; private string directoryCopyFlags = VersionManager.Version >= 6.2 ? "DA" : "T"; #endregion Option Defaults #region Public Properties /// /// The source file path where the RoboCommand is copying files from. /// public virtual string Source { get { return _source; } set { _source = value.CleanDirectoryPath(); } } private string _source; /// /// The destination file path where the RoboCommand is copying files to. /// public virtual string Destination { get { return _destination; } set { _destination = value.CleanDirectoryPath(); } } private string _destination; /// /// Allows you to supply a set of files to copy or use wildcard characters (* or ?).
/// JobOptions file saves these into the /IF (Include Files) section ///
public IEnumerable FileFilter { get { return fileFilter; } set { fileFilter = value; } } /// /// Copies subdirectories. Note that this option excludes empty directories. /// [/S] /// public virtual bool CopySubdirectories { get; set; } /// /// Copies subdirectories. Note that this option includes empty directories. /// [/E] /// public virtual bool CopySubdirectoriesIncludingEmpty { get; set; } /// /// Copies only the top N levels of the source directory tree. The default is /// zero which does not limit the depth. /// [/LEV:N] /// public virtual int Depth { get; set; } /// /// Copies files in Restart mode. /// [/Z] /// public virtual bool EnableRestartMode { get; set; } /// /// Copies files in Backup mode. /// [/B] /// public virtual bool EnableBackupMode { get; set; } /// /// Uses Restart mode. If access is denied, this option uses Backup mode. /// [/ZB] /// public virtual bool EnableRestartModeWithBackupFallback { get; set; } /// /// Copy using unbuffered I/O (recommended for large files). /// [/J] /// public virtual bool UseUnbufferedIo { get; set; } /// /// Copies all encrypted files in EFS RAW mode. /// [/EFSRAW] /// public virtual bool EnableEfsRawMode { get; set; } /// /// This property should be set to a string consisting of all the flags to include (eg. DAT; DATSOU) /// Specifies the file properties to be copied. The following are the valid values for this option: ///D Data ///A Attributes ///T Time stamps ///S NTFS access control list (ACL) ///O Owner information ///U Auditing information ///The default value for copyflags is DAT (data, attributes, and time stamps). ///[/COPY:copyflags] /// public string CopyFlags { get { return copyFlags; } set => copyFlags = value; } /// /// Copies files with security (equivalent to /copy:DAT). /// [/SEC] /// public virtual bool CopyFilesWithSecurity { get; set; } /// /// Copies all file information (equivalent to /copy:DATSOU). /// [/COPYALL] /// public virtual bool CopyAll { get; set; } /// /// Copies no file information (useful with Purge option). /// [/NOCOPY] /// public virtual bool RemoveFileInformation { get; set; } /// /// Fixes file security on all files, even skipped ones. /// [/SECFIX] /// public virtual bool FixFileSecurityOnAllFiles { get; set; } /// /// Fixes file times on all files, even skipped ones. /// [/TIMFIX] /// public virtual bool FixFileTimesOnAllFiles { get; set; } /// /// Deletes destination files and directories that no longer exist in the source. /// [/PURGE] /// public virtual bool Purge { get; set; } /// /// Mirrors a directory tree (equivalent to CopySubdirectoriesIncludingEmpty plus Purge). /// [/MIR] /// public virtual bool Mirror { get; set; } /// /// Moves files, and deletes them from the source after they are copied. /// [/MOV] /// public virtual bool MoveFiles { get; set; } /// /// Moves files and directories, and deletes them from the source after they are copied. /// [/MOVE] /// public virtual bool MoveFilesAndDirectories { get; set; } /// /// This property should be set to a string consisting of all the attributes to add (eg. AH; RASHCNET). /// Adds the specified attributes to copied files. /// [/A+:attributes] /// public string AddAttributes { get; set; } /// /// This property should be set to a string consisting of all the attributes to remove (eg. AH; RASHCNET). /// Removes the specified attributes from copied files. /// [/A-:attributes] /// public string RemoveAttributes { get; set; } /// /// Creates a directory tree and zero-length files only. /// [/CREATE] /// public virtual bool CreateDirectoryAndFileTree { get; set; } /// /// Creates destination files by using 8.3 character-length FAT file names only. /// [/FAT] /// public virtual bool FatFiles { get; set; } /// /// Turns off support for very long paths (longer than 256 characters). /// [/256] /// public virtual bool TurnLongPathSupportOff { get; set; } /// /// The default value of zero indicates that you do not wish to monitor for changes. /// Monitors the source, and runs again when more than N changes are detected. /// [/MON:N] /// public virtual int MonitorSourceChangesLimit { get; set; } /// /// The default value of zero indicates that you do not wish to monitor for changes. /// Monitors source, and runs again in M minutes if changes are detected. /// [/MOT:M] /// public virtual int MonitorSourceTimeLimit { get; set; } /// /// Specifies run times when new copies may be started. ( Copy Operation is scheduled to only operate within specified timeframe ) /// [/rh:hhmm-hhmm]
/// If copy operation is unfinished, robocopy will remain active in idle state until the specified time, at which it will resume copying.
/// Must be in correct format. Incorrectly formatted strings will be ignored. /// Examples:
/// 1500-1800 -> Robocopy will only copy between 3 PM and 5 PM
/// 0015-0530 -> Robocopy will only copy between 12:15 AM and 5:30 AM
///
/// /// If this is set up, then the robocopy process will remain active after the program exits if the calling asemmbly does not call prior to exiting the application. /// public string RunHours { get => runHours; set { if (String.IsNullOrWhiteSpace(value)) runHours = value?.Trim() ?? string.Empty; else if (CheckRunHoursString(value)) runHours = value.Trim(); } } private string runHours; /// /// Checks the scheduled /RH (run hours) per file instead of per pass. /// [/PF] /// public virtual bool CheckPerFile { get; set; } /// /// The default value of zero indicates that this feature is turned off. /// Specifies the inter-packet gap to free bandwidth on slow lines. /// [/IPG:N] /// public virtual int InterPacketGap { get; set; } /// /// Copies the symbolic link instead of the target. /// [/SL] /// public virtual bool CopySymbolicLink { get; set; } /// /// The default value of zero indicates that this feature is turned off. /// Creates multi-threaded copies with N threads. Must be an integer between 1 and 128. /// The MultiThreadedCopiesCount parameter cannot be used with the /IPG and EnableEfsRawMode parameters. /// [/MT:N] /// public virtual int MultiThreadedCopiesCount { get; set; } /// /// What to copy for directories (default is DA). /// (copyflags: D=Data, A=Attributes, T=Timestamps). /// [/DCOPY:copyflags] /// public string DirectoryCopyFlags { get { return directoryCopyFlags; } set { directoryCopyFlags = value; } } /// /// Do not copy any directory info. /// [/NODCOPY] /// public virtual bool DoNotCopyDirectoryInfo { get; set; } /// /// Copy files without using the Windows Copy Offload mechanism. /// [/NOOFFLOAD] /// public virtual bool DoNotUseWindowsCopyOffload { get; set; } #endregion Public Properties #region < Parse (INTERNAL) > /// /// Used by the Parse method to sanitize path for the command options.
/// Evaluate the path. If needed, wrap it in quotes.
/// If the path ends in a DirectorySeperatorChar, santize it to work as expected.
///
/// /// Each return string includes a space at the end of the string to seperate it from the next option variable. private string WrapPath(string path) { if (!path.Contains(" ")) return $"{path} "; //No spaces, just return the path //Below this line, the path contains a space, so it must be wrapped in quotes. if (path.EndsWithDirectorySeperator()) return $"\"{path}.\" "; // Ends with a directory seperator - Requires a '.' to denote using that directory. ex: "F:\." return $"\"{path}\" "; } /// /// Parse the class properties and generate the command arguments /// /// internal string Parse() { Debugger.Instance.DebugMessage("Parsing CopyOptions..."); var version = VersionManager.Version; var options = new StringBuilder(); // Set Source and Destination options.Append(WrapPath(Source)); options.Append(WrapPath(Destination)); // Set FileFilter // Quote each FileFilter item. The quotes are trimmed first to ensure that they are applied only once. var fileFilterQuotedItems = FileFilter.Select(word => "\"" + word.Trim('"') + "\""); string fileFilter = String.Join(" ", fileFilterQuotedItems); options.Append($"{fileFilter} "); Debugger.Instance.DebugMessage(string.Format("Parsing CopyOptions progress ({0}).", options.ToString())); #region Set Options var cleanedCopyFlags = CopyFlags.CleanOptionInput(); var cleanedDirectoryCopyFlags = DirectoryCopyFlags.CleanOptionInput(); if (!cleanedCopyFlags.IsNullOrWhiteSpace()) { options.Append(string.Format(COPY_FLAGS, cleanedCopyFlags)); Debugger.Instance.DebugMessage(string.Format("Parsing CopyOptions progress ({0}).", options.ToString())); } if (!cleanedDirectoryCopyFlags.IsNullOrWhiteSpace() && version >= 5.1260026) { options.Append(string.Format(DIRECTORY_COPY_FLAGS, cleanedDirectoryCopyFlags)); Debugger.Instance.DebugMessage(string.Format("Parsing CopyOptions progress ({0}).", options.ToString())); } if (CopySubdirectories) { options.Append(COPY_SUBDIRECTORIES); Debugger.Instance.DebugMessage(string.Format("Parsing CopyOptions progress ({0}).", options.ToString())); } if (CopySubdirectoriesIncludingEmpty) options.Append(COPY_SUBDIRECTORIES_INCLUDING_EMPTY); if (Depth > 0) options.Append(string.Format(DEPTH, Depth)); if (EnableRestartMode) options.Append(ENABLE_RESTART_MODE); if (EnableBackupMode) options.Append(ENABLE_BACKUP_MODE); if (EnableRestartModeWithBackupFallback) options.Append(ENABLE_RESTART_MODE_WITH_BACKUP_FALLBACK); if (UseUnbufferedIo && version >= 6.2) options.Append(USE_UNBUFFERED_IO); if (EnableEfsRawMode) options.Append(ENABLE_EFSRAW_MODE); if (CopyFilesWithSecurity) options.Append(COPY_FILES_WITH_SECURITY); if (CopyAll) options.Append(COPY_ALL); if (RemoveFileInformation) options.Append(REMOVE_FILE_INFORMATION); if (FixFileSecurityOnAllFiles) options.Append(FIX_FILE_SECURITY_ON_ALL_FILES); if (FixFileTimesOnAllFiles) options.Append(FIX_FILE_TIMES_ON_ALL_FILES); if (Purge) options.Append(PURGE); if (Mirror) options.Append(MIRROR); if (MoveFiles) options.Append(MOVE_FILES); if (MoveFilesAndDirectories) options.Append(MOVE_FILES_AND_DIRECTORIES); if (!AddAttributes.IsNullOrWhiteSpace()) options.Append(string.Format(ADD_ATTRIBUTES, AddAttributes.CleanOptionInput())); if (!RemoveAttributes.IsNullOrWhiteSpace()) options.Append(string.Format(REMOVE_ATTRIBUTES, RemoveAttributes.CleanOptionInput())); if (CreateDirectoryAndFileTree) options.Append(CREATE_DIRECTORY_AND_FILE_TREE); if (FatFiles) options.Append(FAT_FILES); if (TurnLongPathSupportOff) options.Append(TURN_LONG_PATH_SUPPORT_OFF); if (MonitorSourceChangesLimit > 0) options.Append(string.Format(MONITOR_SOURCE_CHANGES_LIMIT, MonitorSourceChangesLimit)); if (MonitorSourceTimeLimit > 0) options.Append(string.Format(MONITOR_SOURCE_TIME_LIMIT, MonitorSourceTimeLimit)); if (!RunHours.IsNullOrWhiteSpace()) options.Append(string.Format(RUN_HOURS, RunHours.CleanOptionInput())); if (CheckPerFile) options.Append(CHECK_PER_FILE); if (InterPacketGap > 0) options.Append(string.Format(INTER_PACKET_GAP, InterPacketGap)); if (CopySymbolicLink) options.Append(COPY_SYMBOLIC_LINK); if (MultiThreadedCopiesCount > 0) options.Append(string.Format(MULTITHREADED_COPIES_COUNT, MultiThreadedCopiesCount)); if (DoNotCopyDirectoryInfo && version >= 6.2) options.Append(DO_NOT_COPY_DIRECTORY_INFO); if (DoNotUseWindowsCopyOffload && version >= 6.2) options.Append(DO_NOT_USE_WINDOWS_COPY_OFFLOAD); #endregion Set Options var parsedOptions = options.ToString(); Debugger.Instance.DebugMessage(string.Format("CopyOptions parsed ({0}).", parsedOptions)); return parsedOptions; } #endregion #region < RunHours (Public) > private static Regex RunHours_OverallRegex = new Regex("^(?[0-2][0-9][0-5][0-9])-(?[0-2][0-9][0-5][0-9])$", RegexOptions.Compiled | RegexOptions.ExplicitCapture); private static Regex RunHours_Check1 = new Regex("^[0-1][0-9][0-5][0-9]$", RegexOptions.Compiled); // Checks 0000 - 1959 private static Regex RunHours_Check2 = new Regex("^[2][0-3][0-5][0-9]$", RegexOptions.Compiled); // Checks 2000 - 2359 private GroupCollection RunHoursGroups => RunHours_OverallRegex.Match(RunHours).Groups; /// /// Get the StartTime portion of /// /// hhmm or String.Empty public string GetRunHours_StartTime() { if (RunHours.IsNullOrWhiteSpace()) return string.Empty; return RunHoursGroups["StartTime"]?.Value ?? String.Empty; } /// /// Get the EndTime portion of /// /// hhmm or String.Empty public string GetRunHours_EndTime() { if (RunHours.IsNullOrWhiteSpace()) return string.Empty; return RunHoursGroups["EndTime"]?.Value ?? String.Empty; } /// /// Method to check if some string is valid for use as with the property. /// /// /// True if correct format, otherwise false public bool CheckRunHoursString(string runHours) { if (string.IsNullOrWhiteSpace(runHours)) return true; if (!RunHours_OverallRegex.IsMatch(runHours.Trim())) return false; var times = RunHours_OverallRegex.Match(runHours.Trim()); bool StartMatch = RunHours_Check1.IsMatch(times.Groups["StartTime"].Value) || RunHours_Check2.IsMatch(times.Groups["StartTime"].Value); bool EndMatch = RunHours_Check1.IsMatch(times.Groups["EndTime"].Value) || RunHours_Check2.IsMatch(times.Groups["EndTime"].Value); return StartMatch && EndMatch; } #endregion #region < Flags > /// /// Enum to define the high-level copy action to be taken by RoboCopy process. /// [Flags] public enum CopyActionFlags { /// /// Default Functionality is to only copy the files within the source directory - does not copy any files within the subfolders. /// Default = 0, /// CopySubdirectories = 1, /// CopySubdirectoriesIncludingEmpty = 2, /// Purge = 4, /// CreateDirectoryAndFileTree = 8, /// MoveFiles = 16, /// MoveFilesAndDirectories = 32, /// Mirror = CopySubdirectoriesIncludingEmpty | Purge, //6 } /// /// Apply the to the command /// /// Options to apply public virtual void ApplyActionFlags(CopyActionFlags flags) { this.CopySubdirectories = flags.HasFlag(CopyActionFlags.CopySubdirectories); this.CopySubdirectoriesIncludingEmpty = flags.HasFlag(CopyActionFlags.CopySubdirectoriesIncludingEmpty); this.Purge = flags.HasFlag(CopyActionFlags.Purge); this.Mirror = flags.HasFlag(CopyActionFlags.Mirror); this.MoveFiles = flags.HasFlag(CopyActionFlags.MoveFiles); this.MoveFilesAndDirectories = flags.HasFlag(CopyActionFlags.MoveFilesAndDirectories); } /// /// Get the representation of this object /// public virtual CopyActionFlags GetCopyActionFlags() { var flags = CopyActionFlags.Default; if (this.CopySubdirectories) flags |=CopyActionFlags.CopySubdirectories; if (this.CopySubdirectoriesIncludingEmpty) flags |=CopyActionFlags.CopySubdirectoriesIncludingEmpty; if (this.Purge) flags |=CopyActionFlags.Purge; if (this.Mirror) flags |=CopyActionFlags.Mirror; if (this.MoveFiles) flags |=CopyActionFlags.MoveFiles; if (this.MoveFilesAndDirectories) flags |=CopyActionFlags.MoveFilesAndDirectories; return flags; } #endregion #region < Other Public Methods > /// /// Combine this object with another CopyOptions object.
/// Any properties marked as true take priority. IEnumerable items are combined. ///
/// /// Source and Destination are only taken from the merged item if this object's Source/Destination values are null/empty.
/// RunHours follows the same rules. /// ///
/// public void Merge(CopyOptions copyOptions) { Source = Source.ReplaceIfEmpty(copyOptions.Source); Destination = Destination.ReplaceIfEmpty(copyOptions.Destination); RunHours = RunHours.ReplaceIfEmpty(copyOptions.RunHours); //int -> Take Greater Value Depth = Depth.GetGreaterVal(copyOptions.Depth); InterPacketGap = InterPacketGap.GetGreaterVal(copyOptions.InterPacketGap); MonitorSourceChangesLimit = MonitorSourceChangesLimit.GetGreaterVal(copyOptions.MonitorSourceChangesLimit); MonitorSourceTimeLimit = MonitorSourceTimeLimit.GetGreaterVal(copyOptions.MonitorSourceTimeLimit); MultiThreadedCopiesCount = MultiThreadedCopiesCount.GetGreaterVal(copyOptions.MultiThreadedCopiesCount); //Flags AddAttributes = AddAttributes.CombineCharArr(copyOptions.AddAttributes); CopyFlags = CopyFlags.CombineCharArr(copyOptions.CopyFlags); DirectoryCopyFlags = DirectoryCopyFlags.CombineCharArr(copyOptions.DirectoryCopyFlags); RemoveAttributes = RemoveAttributes.CombineCharArr(copyOptions.RemoveAttributes); //IEnumerable var list = new List(FileFilter); list.AddRange(copyOptions.FileFilter); FileFilter = list; //Bool CheckPerFile |= copyOptions.CheckPerFile; CopyAll |= copyOptions.CopyAll; CopyFilesWithSecurity |= copyOptions.CopyFilesWithSecurity; CopySubdirectories |= copyOptions.CopySubdirectories; CopySubdirectoriesIncludingEmpty |= copyOptions.CopySubdirectoriesIncludingEmpty; CopySymbolicLink |= copyOptions.CopySymbolicLink; CreateDirectoryAndFileTree |= copyOptions.CreateDirectoryAndFileTree; DoNotCopyDirectoryInfo |= copyOptions.DoNotCopyDirectoryInfo; DoNotUseWindowsCopyOffload |= copyOptions.DoNotUseWindowsCopyOffload; EnableBackupMode |= copyOptions.EnableBackupMode; EnableEfsRawMode |= copyOptions.EnableEfsRawMode; EnableRestartMode |= copyOptions.EnableRestartMode; EnableRestartModeWithBackupFallback |= copyOptions.EnableRestartModeWithBackupFallback; FatFiles |= copyOptions.FatFiles; FixFileSecurityOnAllFiles |= copyOptions.FixFileSecurityOnAllFiles; FixFileTimesOnAllFiles |= copyOptions.FixFileTimesOnAllFiles; Mirror |= copyOptions.Mirror; MoveFiles |= copyOptions.MoveFiles; MoveFilesAndDirectories |= copyOptions.MoveFilesAndDirectories; Purge |= copyOptions.Purge; RemoveFileInformation |= copyOptions.RemoveFileInformation; TurnLongPathSupportOff |= copyOptions.TurnLongPathSupportOff; UseUnbufferedIo |= copyOptions.UseUnbufferedIo; } #endregion } }