2

I am learning C# and want to create a simple backup program using C# winforms.

I have got the program to zip the folder and move it to another location no problems when the files arent in use. How can I do the same if the files are in use or at least ignore the file in use and keep zipping the rest.

My ideal solution would be to copy and zip all files even if they are in use, failing that I want to zip everything it can and print a list of the files that it missed.

Here is the code I am using to zip and send to another location

 private void btnZip_Click(object sender, EventArgs e)
    {
        string fromDirectory = txtBackupFrom.Text;
        string todaysDate = DateTime.Now.ToString("dd_MMM_yyyy");
        string toDirectory = txtBackupToLocation.Text + "/" + todaysDate + "_backup.zip";

        try
        {
            ZipFile.CreateFromDirectory(fromDirectory, toDirectory, CompressionLevel.Optimal, true);
            //Write the current date to the text file

            StreamWriter writer = new StreamWriter(runningDirectory + "\\BackupDate.txt"); //open the file for writing.
            writer.Write(DateTime.Now.ToString("dd MMM yyyy")); //write the current date to the file. change this with your date or something.
            writer.Close(); //remember to close the file again.
            writer.Dispose(); //remember to dispose it from the memory.

            MessageBox.Show("Backup Successful");
        }
        catch (Exception zipException)
        {
            MessageBox.Show(zipException.Message);
        }
    }

/********EDITED BELOW*************/

Here is what I have tried to fix the issues. It may not be the best way as I am learning but it is working

private void btnZip_Click(object sender, EventArgs e)
    {
        //copy location before zipping
        string copytoBeforZippingDirectory = txtBackupToLocation.Text;
        //temporary folder for zipping
        string copytotempDirectory = Path.Combine(copytoBeforZippingDirectory, "Backup_File");
        //where the files are coming from
        string copyfromDirectory = txtBackupFrom.Text;
        //today's date
        string todaysDate = DateTime.Now.ToString("dd_MMM_yyyy");
        //Where the files will end up
        string copytoDirectory = txtBackupToLocation.Text + "\\" + todaysDate + "_backup.zip";

        //Create the new temporary folder for zipping
        Directory.CreateDirectory(copytotempDirectory);

        try
        {
            //Get a list of all files
            string[] fileList = Directory.GetFiles(copyfromDirectory, "*");
            // Copy all files. 
            foreach (string f in fileList)
            {
                // Remove path from the file name. 
                string fName = f.Substring(copyfromDirectory.Length + 1);
                // Use the Path.Combine method to safely append the file name to the path. 
                // Will overwrite if the destination file already exists.
                File.Copy(Path.Combine(copyfromDirectory, fName), Path.Combine(copytotempDirectory, fName), true);
            }
            MessageBox.Show("Files Copied successfully. Beginning Zipping of Files");
        }

        catch (DirectoryNotFoundException dirNotFound)
        {
            MessageBox.Show(dirNotFound.Message);
            Close();
        }
        //Zipping the temporary folder
        try
        {
            ZipFile.CreateFromDirectory(copytotempDirectory, copytoDirectory, CompressionLevel.Optimal, true);
            //Write the current date to the text file
            StreamWriter writer = new StreamWriter(runningDirectory + "\\BackupDate.txt"); //open the file for writing.
            writer.Write(DateTime.Now.ToString("dd MMM yyyy")); //write the current date to the file. change this with your date or something.
            writer.Close(); //remember to close the file again.
            writer.Dispose(); //remember to dispose it from the memory.

            MessageBox.Show("Backup Successful");
        }
        catch (Exception zipException)
        {
            MessageBox.Show(zipException.Message);
        }

        //Remove the temp folder
        try
        {
            Directory.Delete(copytotempDirectory, true);
        }
        catch (Exception)
        {
            MessageBox.Show("Temporary Folder " + copytotempDirectory + " not removed");
        }
    }
WillNZ
  • 765
  • 5
  • 13
  • 38

2 Answers2

1

First of all, for zip a file in C# there is no better option that no using a third-application and instead use the powershell zipper included in Windows.

In any case, you must copy the file to the temporal and then zip the temporal copy.

Leandro Bardelli
  • 10,561
  • 15
  • 79
  • 116
1

Unless you want to do something really destructive you can't touch files that are in use and not expected to be used by other process.

There is a chance that other process allows "share read" so you may try to copy/read content of file in use. Note that it may give you inconsistent data if other application is not careful about writing to the file.

To open file in use with "share read" (many samples, like Is there any way to read data from a locked file?). You may need to try other FileAccess and FileShare options depending on how other process opens the file.

 using (FileStream fileStream = new FileStream(fileName, 
        FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

ZipFile class will not allow you to open file with such mode, so you'll need to either copy (as suggested in Leandro's answer) or manually add files to archive using ZipArchive.Create API.

using (var zipToOpen = new FileStream(@"c:\users\exampleuser\release.zip", FileMode.Open))
{
  using (var archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
  {
    ZipArchiveEntry readmeEntry = 
           archive.CreateEntry("Readme.txt", CompressionLevel.Optimal);
    fileStream.CopyTo(readmeEntry.Open());
  }
}

If you want just skip files that are in use - iterate through all files and have try/catch around code that tries to read the file and skip them. Use ZipArchive to construct/add files one by one.

Community
  • 1
  • 1
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179