Author Topic: [c#] RoutineBackup.cs - Quick and dirty backup  (Read 2029 times)

0 Members and 5 Guests are viewing this topic.

Offline frog

  • Knight
  • **
  • Posts: 232
  • Cookies: 16
    • View Profile
[c#] RoutineBackup.cs - Quick and dirty backup
« on: April 08, 2014, 07:07:17 am »
Need I say more? The program copies everything I want from the user folder to my backup drive. By default, it does not overwrite files or directories; albeit error reporting and progress are non-existent. Needless to say, I put my trust in this script.

My original incarnation of this script had a modified 'CopyDirectory' function which would display a progress bar but would I would have to intervene to tell it not to overwrite files. I needed something that didn't require user-intervention so this is where I landed.

This is my first c# program. Short and sweet.
Code: (csharp) [Select]
// Filename: RoutineBackup.cs
// Purpose: Routine backup of select folders
// Date: April 7th, 2014
using System;
using Microsoft.VisualBasic.FileIO;

namespace RoutineBackup {
    class Program {
        static void Main(string[] args) {
            string sourceDir = @"C:\Users\frog\";
            string destDir = @"D:\";
            string[] dirsToBackup = { "Beats", "Bookmarks", "Downloads", "Desktop", "Music", "Pictures" };

            Console.WriteLine("[+] Starting routine backup at " + DateTime.Now.ToString(
                "h:mm:ss tt ddd MMM dd, yyyy"));

            for(int x = 0; x < dirsToBackup.Length; x++) {
                Console.WriteLine("[-] Copying " + sourceDir + dirsToBackup[x] + " to " + destDir +
                    dirsToBackup[x]);
                try {
                    FileSystem.CopyDirectory(sourceDir + dirsToBackup[x], destDir + dirsToBackup[x],
                        false);
                } catch (System.IO.IOException IOError) {
                    //Console.WriteLine("[!] Error: " + IOError.Data);
                    continue;
                }
            }

            Console.WriteLine("[*] Backup completed at " + DateTime.Now.ToString(
                "h:mm:ss tt ddd MMM dd, yyyy"));
            Console.WriteLine("[!] Press any key to exit..");
            string pause = Console.ReadLine();
        }
    }
}

Offline ArkPhaze

  • Peasant
  • *
  • Posts: 136
  • Cookies: 20
  • null terminated
    • View Profile
Re: [c#] RoutineBackup.cs - Quick and dirty backup
« Reply #1 on: April 14, 2014, 05:40:39 am »
This would be better if it used the Environment class and this functionality itself was encapsulated within a class; everything right now is in the main() function and hardcoded values are in place. Why are you using VisualBasic IO though?

That Try statement is also horrible practice. There's no need to catch an exception if you implemented *proper* error handling. I.e. checking whether all input and the output location exists and whether you can write there or not for instance.
sig=: ArkPhaze

[ J/ASM/.NET/C/C++ - Software Engineer ]

Offline Kulverstukas

  • Administrator
  • Zeus
  • *
  • Posts: 6627
  • Cookies: 542
  • Fascist dictator
    • View Profile
    • My blog
Re: [c#] RoutineBackup.cs - Quick and dirty backup
« Reply #2 on: April 14, 2014, 07:11:15 am »
Indeed it would be much better if it used environmental variables and put all the files in a zip archive. This way it wouldn't have to worry about replacing files.

Here's a batch that I made and use all the time for basic backup of my projects folder. It zips everything up and puts on a remote drive.

Code: [Select]
@echo off

setLocal Enabledelayedexpansion
set pretty_date=%date:~-10,4%-%date:~-5,2%-%date:~-2,2%
del D:\%pretty_date%.zip > nul

"C:\Program Files\7-Zip\7z" a -tzip D:\%pretty_date%.zip "D:\Eclipse_workspace" > nul
for %%d in (c d e f g h i j k l m n o p q r s t u v w x y z) do (
  if exist %%d:\Eclipse-Backup\ (
     move /Y D:\%pretty_date%.zip %%d:\Eclipse-Backup\Eclipse_workspace-%pretty_date%.zip
  )
)

Offline frog

  • Knight
  • **
  • Posts: 232
  • Cookies: 16
    • View Profile
Re: [c#] RoutineBackup.cs - Quick and dirty backup
« Reply #3 on: April 14, 2014, 09:25:14 am »
The program wouldn't compile without the catch in the code. The compiler would throw a fatal error and you would not get a successful build. If the catch statement is there with the proper exception type then the compiler continues as intended and you get a successful build.

I'm using functions from the visualbasic api for the copydirectory function. If you use the copydirectory function from the vb api, you get a progress bar and dialog box just as if you had done it by hand with the mouse/keyboard.

It was more or less just a way for me to get more comfortable using c#.

The program is flawed in many ways. It doesn't check to see if the source file is newer than the destination for the overwrite and there's no structure but hey, it's quick and dirty.

Offline ArkPhaze

  • Peasant
  • *
  • Posts: 136
  • Cookies: 20
  • null terminated
    • View Profile
Re: [c#] RoutineBackup.cs - Quick and dirty backup
« Reply #4 on: April 16, 2014, 03:51:11 am »
Quote
The program wouldn't compile without the catch in the code. The compiler would throw a fatal error and you would not get a successful build. If the catch statement is there with the proper exception type then the compiler continues as intended and you get a successful build.

Are you trying to tell us that we are wrong and that you need the try statement? What I initially mentioned is that you don't need the try statement at all, I never said to only just get rid of the catch block from the try statement. USING a try statement as error handling is more often than not bad practice.

Here's what I said:
Quote
That Try statement is also horrible practice. There's no need to catch an exception if you implemented *proper* error handling. I.e. checking whether all input and the output location exists and whether you can write there or not for instance.

Read about exception handling on MSDN. There is an Exists() method for various classes within the IO namespaces. Catching an exception and swallowing it is not only poor and improper error handling, it also hits performance.

http://msdn.microsoft.com/en-us/library/vstudio/ms229005(v=vs.100).aspx
http://msdn.microsoft.com/en-us/library/5b2yeyab(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/seyhszts(v=vs.110).aspx

http://msdn.microsoft.com/en-us/library/system.io.directory.exists(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/system.io.file.exists.aspx

The other thing is permissions, which can be solved the majority of the time by requiring that process to run elevated, and/or using fileshare.
« Last Edit: April 16, 2014, 03:56:29 am by ArkPhaze »
sig=: ArkPhaze

[ J/ASM/.NET/C/C++ - Software Engineer ]

Offline frog

  • Knight
  • **
  • Posts: 232
  • Cookies: 16
    • View Profile
Re: [c#] RoutineBackup.cs - Quick and dirty backup
« Reply #5 on: April 18, 2014, 11:35:58 am »
Are you trying to tell us that we are wrong and that you need the try statement? What I initially mentioned is that you don't need the try statement at all, I never said to only just get rid of the catch block from the try statement. USING a try statement as error handling is more often than not bad practice.

Here's what I said:
Read about exception handling on MSDN. There is an Exists() method for various classes within the IO namespaces. Catching an exception and swallowing it is not only poor and improper error handling, it also hits performance.

http://msdn.microsoft.com/en-us/library/vstudio/ms229005(v=vs.100).aspx
http://msdn.microsoft.com/en-us/library/5b2yeyab(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/seyhszts(v=vs.110).aspx

http://msdn.microsoft.com/en-us/library/system.io.directory.exists(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/system.io.file.exists.aspx

The other thing is permissions, which can be solved the majority of the time by requiring that process to run elevated, and/or using fileshare.

Point taken. I'm using try/catch statements as a Java habit. I'm aware that you can modify the manifest to require elevated privileges but I still don't see how I can do this w/o a try/catch.

As CopyDirectory() has no return value, I don't see any other way of doing it. How would you handle the exception?

As I said, this is my first c# program.

You never implicated to get rid of the catch block, only that the code posted is 'incorrect'. It still functions, however I am ready to receive strict criticism as the ego dictates.

The CopyDirectory function has no return value, so the only way to check for errors is internally through exceptions thrown by the runtime(try/catch statements). I can't do boolean or integer checks on the function so I have to work within the runtime. This particular function(CopyDirectory) is called from an external library(VisualBasic.FileIO, not part of the traditional System.IO) which is somewhat unconventional so this doesn't surprise me.

If I was feeling fancy enough to use strict file checking(exists/timestamps; all caveats of the System.IO framework), this would not be an issue as I would be handling my exception similar to how I would in a c/c++ program. Booleans and integers. I believe this particular scenario is an exception in itself.
« Last Edit: April 18, 2014, 11:40:27 am by frog »

Offline ArkPhaze

  • Peasant
  • *
  • Posts: 136
  • Cookies: 20
  • null terminated
    • View Profile
Re: [c#] RoutineBackup.cs - Quick and dirty backup
« Reply #6 on: April 20, 2014, 08:02:44 pm »
I gave you links to show you how to validate a few things first that would throw exceptions. You have to start with those. Use the Directory and File classes that exist within the System.IO namespace. A try/catch is not the only way... You just need to know what throws these exceptions. CopyDirectory is irrelevant here, if you're expecting a single function to handle all exceptions for you, then that's an idea to get rid of at this point in time.

If you know that in order to copy a file to another location requires that the file you are moving exists, and the output path exists, and that you have permissions to carry out the action, then it's obvious to see what checks need to be done before you even move the file to prevent an exception from being thrown. What you're doing is expecting the method that moves the file to take care of all of this for you.

For instance, I already provided a link to a few pieces of documentation for you. File.Exists() checks if the file at the specified filepath exists, and Directory has many of the same methods that the File class has, but more geared towards directories instead of files.
« Last Edit: April 20, 2014, 08:06:16 pm by ArkPhaze »
sig=: ArkPhaze

[ J/ASM/.NET/C/C++ - Software Engineer ]

Offline frog

  • Knight
  • **
  • Posts: 232
  • Cookies: 16
    • View Profile
Re: [c#] RoutineBackup.cs - Quick and dirty backup
« Reply #7 on: April 22, 2014, 09:56:59 am »
I gave you links to show you how to validate a few things first that would throw exceptions. You have to start with those. Use the Directory and File classes that exist within the System.IO namespace. A try/catch is not the only way... You just need to know what throws these exceptions. CopyDirectory is irrelevant here, if you're expecting a single function to handle all exceptions for you, then that's an idea to get rid of at this point in time.

If you know that in order to copy a file to another location requires that the file you are moving exists, and the output path exists, and that you have permissions to carry out the action, then it's obvious to see what checks need to be done before you even move the file to prevent an exception from being thrown. What you're doing is expecting the method that moves the file to take care of all of this for you.

For instance, I already provided a link to a few pieces of documentation for you. File.Exists() checks if the file at the specified filepath exists, and Directory has many of the same methods that the File class has, but more geared towards directories instead of files.

I never had the intention of using System.IO from the start. I'm aware the namespace exists and that this is how someone would normally copy files/directories back and forth using c#. I hear what you're saying and I'm already familiar with the concepts you are bringing to the table.

I understand how to work with exceptions, how to check if a file exists, etc. You're saying that I should of done all these things using the System.IO namespace rather than using VisualBasic.FileIO. I get that. I get that you can use if/else statements for exception handling. You're preaching to the quire.

The argument is how would you(otherwise than how I've done) handle an exception from the 'CopyDirectory' function? You can't. You can't do an if/else; it's try/catch or nothing in this case.

I'm aware that I didn't do any validation before the file copy and that I handled the exception in a dirty way. If I had been using System.IO from the start, we wouldn't be having this conversation.

Just because this is my first c# program, does not mean I don't have programming experience.

The script is short and sweet, and does what I need it to(with or without it's flaws). End of story.

I do however, appreciate both you and Kulv's suggestions on how to make it better. I don't however enjoy arguing about what the 'right' way to do something is. I don't always do what is considered the 'right' way, as that's not always what is most important(in my opinion).
« Last Edit: April 22, 2014, 10:01:45 am by frog »

Offline ArkPhaze

  • Peasant
  • *
  • Posts: 136
  • Cookies: 20
  • null terminated
    • View Profile
Re: [c#] RoutineBackup.cs - Quick and dirty backup
« Reply #8 on: April 25, 2014, 01:24:22 am »
Quote
The argument is how would you(otherwise than how I've done) handle an exception from the 'CopyDirectory' function? You can't. You can't do an if/else; it's try/catch or nothing in this case.

Why *would* you handle it from that function? The point is to make the checks prior to the function call to avoid an exception from being thrown. That is proper application design, otherwise, there's something seriously flawed with your design if you're doing otherwise. That's my point, and this is the reason why I told you about functions that exist within the System.IO namespace... It wasn't to suggest that they should replace CopyDirectory, although, that would be my preference, but rather used to avoid using that try statement and swallowing the exception up for absolutely NO reason. They can be used in order to check and validate as to whether an exception will be thrown from the call to CopyDirectory beforehand, and this is what you SHOULD be doing...

If there was no other way, other than a try statement to prevent the exception beforehand, this is the reason why functions become depreciated and are superseded with 'better' ones...
« Last Edit: April 25, 2014, 01:25:46 am by ArkPhaze »
sig=: ArkPhaze

[ J/ASM/.NET/C/C++ - Software Engineer ]

Offline frog

  • Knight
  • **
  • Posts: 232
  • Cookies: 16
    • View Profile
Re: [c#] RoutineBackup.cs - Quick and dirty backup
« Reply #9 on: April 26, 2014, 08:51:44 am »
Why *would* you handle it from that function? The point is to make the checks prior to the function call to avoid an exception from being thrown. That is proper application design, otherwise, there's something seriously flawed with your design if you're doing otherwise. That's my point, and this is the reason why I told you about functions that exist within the System.IO namespace... It wasn't to suggest that they should replace CopyDirectory, although, that would be my preference, but rather used to avoid using that try statement and swallowing the exception up for absolutely NO reason. They can be used in order to check and validate as to whether an exception will be thrown from the call to CopyDirectory beforehand, and this is what you SHOULD be doing...

If there was no other way, other than a try statement to prevent the exception beforehand, this is the reason why functions become depreciated and are superseded with 'better' ones...

Indeed, I agree with you 100%. I was having a hard time getting your point at first.