DEV Community

uni928
uni928

Posted on

Publish a Windows application that automatically backs up files

I created a Windows application that monitors a folder and automatically saves a backup if any files within it are updated.
I hope it will be useful to others, so I would like to release the source and the main body of the application.

Please download ver2.0.0 (latest version) from the following site.
https://drive.google.com/file/d/1OrThTFOwGmDDZ31_sdvwrAUpn5eRJu0W/view?usp=sharing


Description of this application

It monitors a folder and automatically saves a backup when a file in it is updated.

For example, if there is index.php in the Folder folder, if you monitor the Folder folder, a backup file will be automatically generated when index.php is updated.

The format of the backup file is update date_file name.zip.
For example, the file name will be 20240401-123021_index.php.zip.

If you are monitoring the Folder folder, a Folder_BackUP folder will be generated in the same location as the Folder folder and a backup will be generated in it.

If there is a folder in the monitored folder, that folder will also be monitored.
In other words, child elements and grandchild elements will be targeted.

Old data that is more than 4 working days old will be automatically deleted the next time monitoring starts.
(Only the last edited content of each file on that day will remain)

Even if an error occurs during execution, the data in the monitored folder will never be rewritten.
Please use it with confidence.

Potential applications:

  • Excel and Word editing
  • Unity Assets folder
  • Small Illustrator files
  • HTML creation
  • Video editing
  • Programming
  • Many other applications.

If you monitor the Unity Assets folder, a backup will be saved, as shown in the image below.(If you want to monitor your Unity Assets folder, I have a better solution for that in my other article.)

The Assets_BackUP folder is automatically generated.
Example of generating a backup.


I've left the code here so you can check the contents.

using System.IO;
using System.IO.Compression;
using System.Security.Policy;
using static System.Net.WebRequestMethods;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace SephirothAutoBackUP
{
    public partial class Form1 : Form
    {
        private bool isExecuteing = false;

        delegate void SetLabelDelegate();

        public Form1()
        {
            InitializeComponent();
        }

        private void panel1_DragDrop(object sender, DragEventArgs e)
        {
            if (isExecuteing)
            {
                MessageBox.Show(
                    "You cannot drag and drop the folder because it is already being monitored. If you want to monitor another folder, please restart the app.", "OK",
                    MessageBoxButtons.OK, MessageBoxIcon.Question
                    );
                return;
            }
            if (e.Data == null)
            {
                return;
            }
            object? data = e.Data.GetData(DataFormats.FileDrop, false);
            if (data == null)
            {
                return;
            }

            string[] files1 = (string[])data;

            if (files1.Length != 1)
            {
                label1.Text = string.Join('\n', files1) + "\nis being monitored. If you want to stop monitoring, please close the application.";
            }
            else
            {
                string fileKindString = " t H   _";

                if (System.IO.File.Exists(files1[0]))
                {
                    if (!files1[0].Substring(files1[0].LastIndexOf("\\") + 1).Contains("."))
                    {
                        MessageBox.Show(
                        "Files without an extension cannot be registered.", "OK",
                        MessageBoxButtons.OK, MessageBoxIcon.Question
                        );
                        return;
                    }

                    if (files1[0].Substring(files1[0].LastIndexOf("\\") + 1).StartsWith("."))
                    {
                        MessageBox.Show(
                        "You cannot register a file that begins with a comma.", "OK",
                        MessageBoxButtons.OK, MessageBoxIcon.Question
                        );
                        return;
                    }

                    fileKindString = " t @ C  ";
                }

                label1.Text = files1[0] + fileKindString + "is being monitored. If you want to stop monitoring, please close the application.";
            }

            System.IO.File.WriteAllText(Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\\")) + "\\OldPath.txt", string.Join('\n', files1));

            isExecuteing = true;

            button1.Enabled = false;

            try
            {
                foreach (string file in files1)
                {
                    if (System.IO.Directory.Exists(file) && !System.IO.Directory.Exists(file + "_BackUP"))
                    {
                        continue;
                    }
                    try
                    {
                        SephirothAutoBackUPMonitoringData myData = new SephirothAutoBackUPMonitoringData(file);

                        SephirothAutoBackUPMonitoringDeleteList deleteListFunction = new SephirothAutoBackUPMonitoringDeleteList();
                        myData.SetDateList();

                        int resolveCount = 0;
                        for (int i = myData.GetDateList().Count - 1; 0 <= i; i--)
                        {
                            if (resolveCount < 3)
                            {
                                resolveCount++;
                                continue;
                            }
                            myData.SetThinkingList(i);

                            deleteListFunction.Exec(myData);
                        }
                        myData.DeleteList();
                    }
                    catch
                    {
                    }
                }
            }
            catch
            { 

            }

            Task.Run(() => Execute(files1));
        }

        private void Execute(string[] files)
        {
            try
            {
                while(true)
                {
                    try
                    {
                        ExecuteOneTime(files);
                        Thread.Sleep(5000);
                    }
                    catch
                    {

                    }
                }
            }
            catch
            {
                Invoke(new SetLabelDelegate(SetLabel));
                isExecuteing = false;
            }
        }

        private void ExecuteOneTime(string[] files)
        {
            foreach(string file in files)
            {
                try
                {
                    if (System.IO.File.Exists(file))
                    {
                        string fileName = file.Substring(file.LastIndexOf("\\") + 1);
                        string zipFileName = file.Substring(0, file.LastIndexOf("\\") + 1) + System.IO.File.GetLastWriteTime(file).ToString("yyyyMMdd-HHmmss") + "_" + fileName + ".zip";

                        if (!System.IO.File.Exists(zipFileName))
                        {

                            bool isCreateFolder = false;

                            string oneTimeDirectoryName = file.Substring(0, file.LastIndexOf("."));
                            if (!System.IO.Directory.Exists(oneTimeDirectoryName))
                            {
                                isCreateFolder = true;
                                System.IO.Directory.CreateDirectory(oneTimeDirectoryName);
                            }
                            System.IO.File.Copy(file, oneTimeDirectoryName + "\\" + fileName);
                            ZipFile.CreateFromDirectory(oneTimeDirectoryName, zipFileName);
                            if (isCreateFolder)
                            {
                                System.IO.File.Delete(oneTimeDirectoryName + "\\" + fileName);
                                System.IO.Directory.Delete(oneTimeDirectoryName);
                            }
                        }

                        return;
                    }
                    foreach (string oneFilePath in System.IO.Directory.GetFiles(file, "*", SearchOption.AllDirectories))
                    {
                        if (oneFilePath.EndsWith(".zip"))
                        {
                            continue;
                        }

                        string fileName = oneFilePath.Substring(oneFilePath.LastIndexOf("\\") + 1);

                        if (!fileName.Contains("."))
                        {
                            continue;
                        }

                        if (fileName.StartsWith(".") || fileName.StartsWith("~"))
                        {
                            continue;
                        }

                        string folderPath = file + "_BackUP";
                        string[] pathMove = oneFilePath.Substring(file.Length + 1).Split("\\");

                        for (int i = 0; i < pathMove.Length - 1; i++)
                        {
                            folderPath = folderPath + "\\" + pathMove[i];
                            if (System.IO.Directory.Exists(folderPath))
                            {
                                System.IO.Directory.CreateDirectory(folderPath);
                            }
                        }

                        string zipFileName = folderPath + "\\" + System.IO.File.GetLastWriteTime(oneFilePath).ToString("yyyyMMdd-HHmmss") + "_" + fileName + ".zip";

                        if (!System.IO.File.Exists(zipFileName))
                        {

                            bool isCreateFolder = false;

                            string oneTimeDirectoryName = folderPath + "\\" + fileName.Substring(0, fileName.LastIndexOf("."));
                            if (!System.IO.Directory.Exists(oneTimeDirectoryName))
                            {
                                isCreateFolder = true;
                                System.IO.Directory.CreateDirectory(oneTimeDirectoryName);
                            }
                            System.IO.File.Copy(oneFilePath, oneTimeDirectoryName + "\\" + fileName);
                            ZipFile.CreateFromDirectory(oneTimeDirectoryName, zipFileName);
                            if (isCreateFolder)
                            {
                                System.IO.File.Delete(oneTimeDirectoryName + "\\" + fileName);
                                System.IO.Directory.Delete(oneTimeDirectoryName);
                            }
                        }
                    }
                }
                catch
                {

                }
            }
        }

        private void SetLabel()
        {
            label1.Text = "Monitoring will end due to an error.";
        }

        private void panel1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data == null)
            {
                return;
            }
            if (e.Data.GetDataPresent(DataFormats.FileDrop) && !isExecuteing)
            {
                e.Effect = DragDropEffects.All;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if(isExecuteing)
            {
                MessageBox.Show(
                "Could not execute because monitoring is already in progress.", "OK",
                MessageBoxButtons.OK, MessageBoxIcon.Question
                );
                return;
            }

            try
            {
                string loadPath = System.IO.File.ReadAllText(Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\\")) + "\\OldPath.txt");

                string[] paths = loadPath.Split("\n");

                foreach(string path in paths)
                {

                    if (!System.IO.Directory.Exists(path) && !System.IO.File.Exists(path))
                    {
                        MessageBox.Show(
                        "The previous path did not exist, so monitoring was not possible.", "OK",
                        MessageBoxButtons.OK, MessageBoxIcon.Question
                        );
                        return;
                    }
                }

                if(paths.Length != 1)
                {
                    label1.Text = string.Join('\n', paths) + "\nis being monitored. If you want to stop monitoring, please close the application.";
                }
                else
                {
                    string fileKindString = " t H   _";

                    if (System.IO.File.Exists(paths[0]))
                    {
                        fileKindString = " t @ C  ";
                    }

                    label1.Text = paths[0] + fileKindString + "is being monitored. If you want to stop monitoring, please close the application.";
                }

                isExecuteing = true;

                button1.Enabled = false;

                try
                {
                    foreach (string file in paths)
                    {
                        if (System.IO.Directory.Exists(file) && !System.IO.Directory.Exists(file + "_BackUP"))
                        {
                            continue;
                        }
                        try
                        {
                            SephirothAutoBackUPMonitoringData myData = new SephirothAutoBackUPMonitoringData(file);

                            SephirothAutoBackUPMonitoringDeleteList deleteListFunction = new SephirothAutoBackUPMonitoringDeleteList();
                            myData.SetDateList();

                            int resolveCount = 0;
                            for (int i = myData.GetDateList().Count - 1; 0 <= i; i--)
                            {
                                if (resolveCount < 3)
                                {
                                    resolveCount++;
                                    continue;
                                }
                                myData.SetThinkingList(i);

                                deleteListFunction.Exec(myData);
                            }
                            myData.DeleteList();
                        }
                        catch
                        {
                        }
                    }
                }
                catch
                {

                }

                Task.Run(() => Execute(paths));
            }
            catch
            {
                MessageBox.Show(
                "The previous path did not exist, so monitoring was not possible.", "OK",
                MessageBoxButtons.OK, MessageBoxIcon.Question
                );
            }
        }
    }

    public class SephirothAutoBackUPMonitoringData
    {
        private string onePath = "";
        private List<string> DateList = new();
        private List<string> thinkingList = new();


        public SephirothAutoBackUPMonitoringData(string onePath)
        {
            this.onePath = onePath;
        }

        public void SetDateList()
        {
            SephirothAutoBackUPMonitoringCreateDateList func = new SephirothAutoBackUPMonitoringCreateDateList();

            DateList = func.CreateDateList(onePath);
        }

        public List<string> GetDateList()
        {
            return DateList;
        }

        public void SetThinkingList(int index)
        {
            SephirothAutoBackUPMonitoringCreateThinkingList func = new SephirothAutoBackUPMonitoringCreateThinkingList();

            thinkingList = func.CreateThinkingList(DateList, index, onePath);
        }

        public List<string> GetThinkingList()
        {
            return thinkingList;
        }

        public void DeleteList()
        {
            DateList = new();
            thinkingList = new();
        }
    }

    public class SephirothAutoBackUPMonitoringCreateDateList
    {
        public List<string> CreateDateList(string path)
        {
            List<string> resultList = new();
            if (System.IO.File.Exists(path))
            {
                foreach(string one in System.IO.Directory.GetFiles(path.Substring(0, path.LastIndexOf("\\")), "*", System.IO.SearchOption.AllDirectories))
                {
                    string oneFileName = one.Substring(one.LastIndexOf("\\") + 1);
                    string pathFileName = path.Substring(path.LastIndexOf("\\") + 1);

                    if (oneFileName.EndsWith(pathFileName + ".zip"))
                    {
                        string fileName = oneFileName;

                        if (fileName.Length < 18)
                        {
                            continue;
                        }

                        try
                        {
                            int.Parse(fileName.Substring(0, 8));
                            int.Parse(fileName.Substring(9, 6));
                            string lookingDate = fileName.Substring(0, 8);

                            bool hasContain = false;

                            foreach (string one2 in resultList)
                            {
                                if (one2 == lookingDate)
                                {
                                    hasContain = true;
                                    break;
                                }
                            }

                            if (!hasContain)
                            {
                                resultList.Add(lookingDate);
                            }
                        }
                        catch
                        {

                        }
                    }
                }
            }
            else
            {
                foreach (string onePath in System.IO.Directory.GetFiles(path + "_BackUP", "*", System.IO.SearchOption.AllDirectories))
                {
                    string fileName = onePath.Substring(onePath.LastIndexOf("\\") + 1);

                    if (fileName.Length < 18)
                    {
                        continue;
                    }

                    try
                    {
                        int.Parse(fileName.Substring(0, 8));
                        int.Parse(fileName.Substring(9, 6));
                        string lookingDate = fileName.Substring(0, 8);

                        bool hasContain = false;

                        foreach (string one in resultList)
                        {
                            if (one == lookingDate)
                            {
                                hasContain = true;
                                break;
                            }
                        }

                        if (!hasContain)
                        {
                            resultList.Add(lookingDate);
                        }
                    }
                    catch
                    {

                    }
                }
            }

            for (int i = 0; i < resultList.Count; i++)
            {
                for (int j = i + 1; j < resultList.Count; j++)
                {
                    if (int.Parse(resultList[j]) < int.Parse(resultList[i]))
                    {
                        string oneTimeString = resultList[i];
                        resultList[i] = resultList[j];
                        resultList[j] = oneTimeString;
                    }
                }
            }

            return resultList;
        }
    }

    public class SephirothAutoBackUPMonitoringCreateThinkingList
    {
        public List<string> CreateThinkingList(List<string> DateList, int index, string path)
        {
            List<string> resultList = new();

            if (System.IO.File.Exists(path))
            {
                foreach (string onePath in System.IO.Directory.GetFiles(path.Substring(0, path.LastIndexOf("\\")), "*", System.IO.SearchOption.AllDirectories))
                {
                    string oneFileName = onePath.Substring(onePath.LastIndexOf("\\") + 1);
                    string pathFileName = path.Substring(path.LastIndexOf("\\") + 1);

                    if (oneFileName.EndsWith(pathFileName + ".zip"))
                    {
                        string fileName = oneFileName;
                        if (fileName.Length < 18)
                        {
                            continue;
                        }

                        if (fileName.StartsWith(DateList[index]))
                        {
                            try
                            {
                                int.Parse(fileName.Substring(0, 8));
                                int.Parse(fileName.Substring(9, 6));
                                resultList.Add(onePath);
                            }
                            catch
                            {

                            }
                        }
                    }
                }
            }
            else
            {
                foreach (string onePath in System.IO.Directory.GetFiles(path + "_BackUP", "*", System.IO.SearchOption.AllDirectories))
                {
                    string fileName = onePath.Substring(onePath.LastIndexOf("\\") + 1);
                    if (fileName.Length < 18)
                    {
                        continue;
                    }

                    if (fileName.StartsWith(DateList[index]))
                    {
                        try
                        {
                            int.Parse(fileName.Substring(0, 8));
                            int.Parse(fileName.Substring(9, 6));
                            resultList.Add(onePath);
                        }
                        catch
                        {

                        }
                    }
                }
            }

            for (int i2 = 0; i2 < resultList.Count; i2++)
            {
                for (int j2 = 0; j2 < resultList.Count; j2++)
                {
                    string fileName1 = resultList[i2].Substring(resultList[i2].LastIndexOf("\\") + 1);
                    fileName1 = fileName1.Substring(0, 8) + fileName1.Substring(9, 6);

                    string fileName2 = resultList[j2].Substring(resultList[j2].LastIndexOf("\\") + 1);
                    fileName2 = fileName2.Substring(0, 8) + fileName2.Substring(9, 6);
                    if (long.Parse(fileName2) < long.Parse(fileName1))
                    {
                        string oneTimeString = resultList[i2];
                        resultList[i2] = resultList[j2];
                        resultList[j2] = oneTimeString;
                    }
                }
            }
            return resultList;
        }
    }

    public class SephirothAutoBackUPMonitoringDeleteList
    {
        public void Exec(SephirothAutoBackUPMonitoringData data)
        {
            System.Collections.Generic.List<string> deleteList = new();

            for (int j = 0; j < data.GetThinkingList().Count; j++)
            {
                bool isContain = false;

                string fileName = data.GetThinkingList()[j].Substring(data.GetThinkingList()[j].LastIndexOf("\\") + 1);

                foreach (string oneDelete in deleteList)
                {

                    if ((data.GetThinkingList()[j].Substring(0, data.GetThinkingList()[j].LastIndexOf("\\")) + "\\" + fileName.Substring(18)) == oneDelete)
                    {
                        isContain = true;
                        break;
                    }
                }

                if (isContain)
                {
                    System.IO.File.Delete(data.GetThinkingList()[j]);
                }
                else
                {
                    deleteList.Add(data.GetThinkingList()[j].Substring(0, data.GetThinkingList()[j].LastIndexOf("\\")) + "\\" + fileName.Substring(18));
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

We have publish an automatic backup Windows application.

We hope that it will be useful for your development.
Thank you for watching.

Top comments (0)