using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace Xylem.Common.Utils.FileIo { /// /// Information about system and and control of resources. /// [Serializable] public class SystemControl { /// /// Names of registered drives of system /// public readonly List DriveNames = new List(); /// /// Scan all used drive letters /// public void DetectAllDrives() { var drives = DriveInfo.GetDrives(); DriveNames.Clear(); foreach (var d in drives) { //if (_driveNames.IsReady) needs to be used to access VolumeLabel, otherwise an IOException will be rose DriveNames.Add(d.Name); } } /// /// Search if file exists and can be opened, exception will be thrown if not. /// /// file identified by name and path /// true if file is locked through other process public static Boolean FileAccessLocked(String fileNamePath) { // if the file does not exits it should be free for usage! if (!File.Exists(fileNamePath)) return false; try { using (var fs = new FileStream(fileNamePath, FileMode.Open)) { if (fs.CanWrite) return false; } } catch (IOException) { return true; } return false; } /// /// Erase and remove entire directory /// /// /// true if directory was removed public static Boolean RemoveDirectory(String path) { if (!Directory.Exists(path)) return true; var trials = 3; try { var filesNamePath = Directory.GetFiles(path); do { foreach (var s in filesNamePath) { if (!FileAccessLocked(s)) { // Delete all files File.Delete(s); } } //check how many files remained filesNamePath = Directory.GetFiles(path); } while (filesNamePath.Length > 0 && trials-- > 0); if (filesNamePath.Length == 0) { Directory.Delete(path); } return !Directory.Exists(path); } catch (IOException) { return false; } } /// /// Compares file information: name, size and last write date. /// /// /// /// true if file information is identical public static Boolean FilesAreIdentical(FileInfo fileNamePath1, FileInfo fileNamePath2) { return fileNamePath1.Name == fileNamePath2.Name && fileNamePath1.LastWriteTime == fileNamePath2.LastWriteTime && fileNamePath1.Length == fileNamePath2.Length; } /// /// Check an entire directory of all files existing. /// /// /// /// /// true if path existing and containing files /// /// - Initial. /// /// /// - Search pattern added. /// public static Boolean GetFilesOfDirectoryAndSubDirectory( String filePath, List fileList, String searchPattern = "*.*") { var files = Directory.GetFiles(filePath, searchPattern); fileList.AddRange(files); // get the subdirectories of the source path var sourcePathDirInfo = new DirectoryInfo(filePath); var sourcePathSubDirInfos = sourcePathDirInfo.GetDirectories(); foreach (var sd in sourcePathSubDirInfos) { files = Directory.GetFiles(sd.FullName); fileList.AddRange(files); } return fileList.Count == 0; } /// /// Check path existence and files in path and return number rof files in path. /// /// /// true if path existing and containing files /// /// - Initial. /// public static Int32 NumberOfFilesInPath( String filePath) { if (Directory.Exists(filePath) && Directory.GetFiles(filePath).Length > 0) return Directory.GetFiles(filePath).Length; return 0; } /// /// Check path existence and files in path. /// /// /// true if path existing and containing files /// /// - Initial. /// public static Boolean FilesExistingInPath( String filePath) { return Directory.Exists(filePath) && Directory.GetFiles(filePath).Length > 0; } /// /// Copy file from source to destination, skip if identical. /// /// /// /// false if the file cannot be copied /// /// - Initial. /// public static Boolean CopyFile(String sourceFilePathName, String destFilePathName) { try { if (string.IsNullOrEmpty(sourceFilePathName) || string.IsNullOrEmpty(destFilePathName)) return false; // without a source file there is nothing to copy if (!File.Exists(sourceFilePathName)) return false; // if a destination file is already there, it has to be checked of being identical if (File.Exists(destFilePathName)) { var srcFileInfo = new FileInfo(sourceFilePathName); var destFileInfo = new FileInfo(destFilePathName); // if the file exist and is identical everything is as it should be if (FilesAreIdentical(srcFileInfo, destFileInfo)) return true; if (FileAccessLocked(destFilePathName)) return false; // remove file if it exist and is not identical File.Delete(destFilePathName); // if the deletion routine failed if (File.Exists(destFilePathName)) return false; // file is erased and can now be copied File.Copy(sourceFilePathName, destFilePathName); return File.Exists(destFilePathName); } // the file is not in the destination directory so it has to be created File.Copy(sourceFilePathName, destFilePathName); return File.Exists(destFilePathName); } catch (IOException) { return false; } } /// /// Build destination path and copy entire directory from source path. /// Compares files which are already in path and skip copy of identical files. /// Include sub-directories. /// /// /// /// false if at least one file cannot be copied or destination folder /// cannot be created /// /// - Copy all sub-directories. /// public static Boolean CopyDirectory(String sourcePath, String destPath) { try { if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(destPath)) return false; if (!Directory.Exists(sourcePath)) return false; // get the subdirectories of the source path var sourcePathDirInfo = new DirectoryInfo(sourcePath); var sourcePathSubDirInfos = sourcePathDirInfo.GetDirectories(); if (!Directory.Exists(destPath)) { Directory.CreateDirectory(destPath); } if (!Directory.Exists(destPath)) return false; var sourceFilesNamePath = Directory.GetFiles(sourcePath); var destFilesNamePath = Directory.GetFiles(destPath); //build a list of files which needed to b e copied as they are not identical var sourceFileNameCopyList = sourceFilesNamePath.Select(Path.GetFileName).ToList(); // build lists of file information for date and size comparison var sourceFilesInfo = sourceFilesNamePath.Select(s => new FileInfo(s)).ToList(); var destFilesInfo = destFilesNamePath.Select(d => new FileInfo(d)).ToList(); // compare attributes of files to skip copy of identical files foreach (var si in from di in destFilesInfo from si in sourceFilesInfo where FilesAreIdentical(si, di) select si) { sourceFileNameCopyList.Remove(si.Name); } // the destFileCtr represents the files which are already in destination folder var destFileCtr = sourceFilesNamePath.Length - sourceFileNameCopyList.Count; foreach (var s in sourceFileNameCopyList) { var destFileNamePath = Path.Combine(destPath, s); var sourceFileNamePath = Path.Combine(sourcePath, s); if (FileAccessLocked(destFileNamePath)) continue; // copy file and overwrite if exists File.Copy(sourceFileNamePath, destFileNamePath, true); destFileCtr++; } // recursive call foreach (var sourceSubDirInfo in sourcePathSubDirInfos) { var destSubDirPath = Path.Combine(destPath, sourceSubDirInfo.Name); if (!CopyDirectory(sourceSubDirInfo.FullName, destSubDirPath)) return false; } return destFileCtr == sourceFilesNamePath.Length; } catch (IOException) { return false; } } } }