laatzen/Common/Utils/FileIoShared/SystemControl.cs
2021-10-01 11:09:20 +02:00

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;
}
}
}
}