Skip to content

Instantly share code, notes, and snippets.

@Biendeo
Created June 30, 2017 00:38
Show Gist options
  • Select an option

  • Save Biendeo/8577831c857ae1a74b68c92500c1d43e to your computer and use it in GitHub Desktop.

Select an option

Save Biendeo/8577831c857ae1a74b68c92500c1d43e to your computer and use it in GitHub Desktop.
Auto Directory Archiver
using IniParser;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
namespace Auto_Directory_Archiver {
class Program {
private const string configPath = "config.ini";
private static bool recursive;
private static string watchFolderPath;
private static string archiveFolderPath;
private static string sevenZipPath;
private static string sevenZipArchiveArguments;
private static string sevenZipExtractArguments;
private static int updateFrequency;
private static bool outputLog = true;
private static string logPath;
private static DateTime lastUpdated;
private const string fmt = "yyyy-MM-dd-HH-mm-ss";
private const int minimumUpdateFrequency = 30;
static void Main(string[] args) {
Log(TraceLevel.Info, "Program starting up");
LoadConfig();
if (updateFrequency < minimumUpdateFrequency) {
updateFrequency = minimumUpdateFrequency;
}
System.Timers.Timer timer = new System.Timers.Timer(SecondsToNextHour() * 1000);
timer.Elapsed += ((object src, ElapsedEventArgs e) => {
timer.Enabled = false;
RecursiveArchiveChangedFiles(watchFolderPath);
lastUpdated = DateTime.Now;
Log(TraceLevel.Info, $"Next update will check at {lastUpdated.AddSeconds(updateFrequency).ToString(fmt)}");
SaveConfig();
timer.Enabled = true;
});
timer.Enabled = true;
Log(TraceLevel.Info, $"Program all set up, next update at {lastUpdated.AddSeconds(updateFrequency).ToString(fmt)}");
while (true) {
Thread.Sleep(int.MaxValue);
}
}
private static int SecondsToNextHour() {
if (lastUpdated.AddSeconds(updateFrequency) < DateTime.Now) {
return minimumUpdateFrequency; // This buys time to archive everything.
} else {
return (int)(lastUpdated.AddSeconds(updateFrequency) - DateTime.Now).TotalSeconds;
}
}
private static bool HasFolderBeenUpdated(string folderPath) {
DateTime lastModified = Directory.GetLastWriteTime(watchFolderPath);
if (lastModified >= lastUpdated) {
return true;
} else {
return false;
}
}
private static void RecursiveArchiveChangedFiles(string folderPath) {
foreach (var file in Directory.EnumerateFiles(folderPath)) {
// Console.WriteLine(Path.GetDirectoryName(GetArchiveFilePath(file)));
// Console.WriteLine($"{file} matches {(new DirectoryInfo(Path.GetDirectoryName(GetArchiveFilePath(file))).GetFiles($"{Path.GetFileName(file)}*").Count())} times");
int numberOfArchives = 0;
try {
numberOfArchives = new DirectoryInfo(Path.GetDirectoryName(GetArchiveFilePath(file))).GetFiles($"{Path.GetFileName(file)}*").Count();
} catch {
Console.WriteLine($"Exception thrown at {file}");
}
if (File.GetLastWriteTime(file) >= lastUpdated ||numberOfArchives == 0) {
SevenZipArchive(file, Path.GetDirectoryName(GetArchiveFilePath(file)), $"{Path.GetFileName(file)} {DateTime.Now.ToString(fmt)}.7z");
Log(TraceLevel.Info, $"Archived {file} to {Path.GetFileName(file)} {DateTime.Now.ToString(fmt)}.7z");
}
}
if (recursive) {
foreach (var dir in Directory.EnumerateDirectories(folderPath)) {
RecursiveArchiveChangedFiles(dir);
}
}
}
private static string GetArchiveFilePath(string watchFolderFilePath) {
return Path.GetFullPath(archiveFolderPath) + GetCommonFilePath(watchFolderFilePath);
}
private static string GetCommonFilePath(string filePath) {
return Path.GetFullPath(filePath).Remove(0, Path.GetFullPath(watchFolderPath).Length);
}
private static string GetArchiveEquivalentFilePath(string originalFilePath) {
return Path.GetFullPath(archiveFolderPath) + originalFilePath.Remove(0, Path.GetFullPath(watchFolderPath).Length);
}
private static void SevenZipArchive(string itemPath, string archiveFolder, string archiveName) {
var processStartInfo = new ProcessStartInfo(sevenZipPath, $"a -t7z \"{archiveFolder}/{archiveName}\" {sevenZipArchiveArguments} \"{itemPath}\"") {
CreateNoWindow = true,
UseShellExecute = false
};
var proc = Process.Start(processStartInfo);
proc.WaitForExit();
}
private static void DefaultConfig() {
watchFolderPath = "./";
archiveFolderPath = "./Archive/";
recursive = true;
sevenZipPath = "C:/Program Files/7-Zip/7z.exe";
sevenZipArchiveArguments = "";
sevenZipExtractArguments = "";
outputLog = true;
logPath = "log.txt";
lastUpdated = DateTime.Now.AddHours(-1);
updateFrequency = 3600;
}
private static void LoadConfig() {
DefaultConfig();
if (File.Exists(configPath)) {
var iniParser = new FileIniDataParser();
var data = iniParser.ReadFile(configPath);
recursive = data["settings"]["recursive"] == "true" ? true : false;
int.TryParse(data["settings"]["updateFrequency"], out updateFrequency);
watchFolderPath = data["settings"]["watchFolderPath"];
archiveFolderPath = data["settings"]["archiveFolderPath"];
sevenZipPath = data["settings"]["sevenZipPath"];
sevenZipArchiveArguments = data["settings"]["sevenZipArchiveArguments"];
sevenZipExtractArguments = data["settings"]["sevenZipExtractArguments"];
outputLog = data["debug"]["outputLog"] == "true" ? true : false;
logPath = data["debug"]["logPath"];
try {
lastUpdated = DateTime.ParseExact(data["sensitive"]["lastUpdate"], fmt, CultureInfo.InvariantCulture);
} catch {
lastUpdated = DateTime.Now.AddHours(-1);
}
Log(TraceLevel.Info, "Loaded config");
} else {
Log(TraceLevel.Info, "No config found, default config assumed");
SaveConfig();
}
}
private static void SaveConfig() {
var iniParser = new FileIniDataParser();
var data = new IniParser.Model.IniData();
data["settings"]["recursive"] = recursive ? "true" : "false";
data["settings"]["updateFrequency"] = updateFrequency.ToString();
data["settings"]["watchFolderPath"] = watchFolderPath;
data["settings"]["archiveFolderPath"] = archiveFolderPath;
data["settings"]["sevenZipPath"] = sevenZipPath;
data["settings"]["sevenZipArchiveArguments"] = sevenZipArchiveArguments;
data["settings"]["sevenZipExtractArguments"] = sevenZipExtractArguments;
data["debug"]["outputLog"] = outputLog ? "true" : "false";
data["debug"]["logPath"] = logPath;
data["sensitive"]["lastUpdate"] = lastUpdated.ToString(fmt);
iniParser.WriteFile(configPath, data);
Log(TraceLevel.Info, "Saved config");
}
private static void Log(TraceLevel level, string message) {
string outputString = $"{DateTime.Now.ToString("dd/MM/yy hh:mm:ss")} [{level}] - {message}";
Console.WriteLine(outputString);
if (!outputLog) {
return;
}
try {
using (var log = File.AppendText(logPath)) {
log.WriteLine(outputString);
}
} catch (Exception e) {
if (e is UnauthorizedAccessException) {
Console.WriteLine($"{DateTime.Now.ToString("dd/MM/yy hh:mm:ss")} [ERROR] - Log file encountered an UnauthorizedAccessException");
} else if (e is PathTooLongException) {
Console.WriteLine($"{DateTime.Now.ToString("dd/MM/yy hh:mm:ss")} [ERROR] - Log file encountered a PathTooLongException");
} else if (e is DirectoryNotFoundException) {
Console.WriteLine($"{DateTime.Now.ToString("dd/MM/yy hh:mm:ss")} [ERROR] - Log file encountered a DirectoryNotFoundException");
} else if (e is NotSupportedException) {
Console.WriteLine($"{DateTime.Now.ToString("dd/MM/yy hh:mm:ss")} [ERROR] - Log file encountered a NotSupportedException");
} else {
Console.WriteLine($"{DateTime.Now.ToString("dd/MM/yy hh:mm:ss")} [ERROR] - Log file encountered an error");
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment