299 lines
11 KiB
C#
299 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace Xylem.Common.Utils.FileIo
|
|
{
|
|
/// <summary>
|
|
/// Information about system and and control of resources.
|
|
/// </summary>
|
|
[Serializable]
|
|
public class SystemControl
|
|
{
|
|
///<summary>
|
|
/// Names of registered drives of system
|
|
/// </summary>
|
|
public readonly List<String> DriveNames = new List<String>();
|
|
|
|
/// <summary>
|
|
/// Scan all used drive letters
|
|
/// </summary>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Search if file exists and can be opened, exception will be thrown if not.
|
|
/// </summary>
|
|
/// <param name="fileNamePath">file identified by name and path</param>
|
|
/// <returns>true if file is locked through other process</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Erase and remove entire directory
|
|
/// </summary>
|
|
/// <param name="path"></param>
|
|
/// <returns>true if directory was removed</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compares file information: name, size and last write date.
|
|
/// </summary>
|
|
/// <param name="fileNamePath1"></param>
|
|
/// <param name="fileNamePath2"></param>
|
|
/// <returns>true if file information is identical</returns>
|
|
public static Boolean FilesAreIdentical(FileInfo fileNamePath1, FileInfo fileNamePath2)
|
|
{
|
|
return fileNamePath1.Name == fileNamePath2.Name
|
|
&& fileNamePath1.LastWriteTime == fileNamePath2.LastWriteTime
|
|
&& fileNamePath1.Length == fileNamePath2.Length;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check an entire directory of all files existing.
|
|
/// </summary>
|
|
/// <param name="filePath"></param>
|
|
/// <param name="fileList"></param>
|
|
/// <param name="searchPattern"></param>
|
|
/// <returns>true if path existing and containing files </returns>
|
|
/// <remarks date="2021-Mar-24" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <remarks date="2021-Mar-29" author="Thomas Wiedebusch">
|
|
/// - Search pattern added.
|
|
/// </remarks>
|
|
public static Boolean GetFilesOfDirectoryAndSubDirectory( String filePath, List<String> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check path existence and files in path and return number rof files in path.
|
|
/// </summary>
|
|
/// <param name="filePath"></param>
|
|
/// <returns>true if path existing and containing files </returns>
|
|
/// <remarks date="2021-Apr-12" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
public static Int32 NumberOfFilesInPath( String filePath)
|
|
{
|
|
if (Directory.Exists(filePath) && Directory.GetFiles(filePath).Length > 0)
|
|
return Directory.GetFiles(filePath).Length;
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check path existence and files in path.
|
|
/// </summary>
|
|
/// <param name="filePath"></param>
|
|
/// <returns>true if path existing and containing files </returns>
|
|
/// <remarks date="2021-Mar-20" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
public static Boolean FilesExistingInPath( String filePath)
|
|
{
|
|
return Directory.Exists(filePath) && Directory.GetFiles(filePath).Length > 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy file from source to destination, skip if identical.
|
|
/// </summary>
|
|
/// <param name="sourceFilePathName"></param>
|
|
/// <param name="destFilePathName"></param>
|
|
/// <returns>false if the file cannot be copied</returns>
|
|
/// <remarks date="2021-Mar-18" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="sourcePath"></param>
|
|
/// <param name="destPath"></param>
|
|
/// <returns>false if at least one file cannot be copied or destination folder
|
|
/// cannot be created</returns>
|
|
/// <remarks date="2021-Mar-18" author="Thomas Wiedebusch">
|
|
/// - Copy all sub-directories.
|
|
/// </remarks>
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|