Introduction
In this post, we will make a basic console application that copies all the files from the source path to destination path, checking if there are files already present at the destination path and doing a simple comparison.
I recommend that if you are following along, you should go and get the code from here, this way, we are sure that we are using the same code state.
Table of Contents
- Step 1 – Setting Up the Project
- Step 2 – The Code Implementation
- Step 3 – Conclusion
If you went and got the solution from the link above, you should have a solution called FileSystemSyncher, otherwise, I would advice to create a solution with the same name so that we do not encounter any confusions down the line.
Open up the solution in Visual Studio and you should see in the Solution Explorer something like figure 1.1.
Figure 1.1
Now we are going to right click on the solution and select Add > New Project… and then we will be prompted with the Add New Project dialog (figure 1.2), then we select the Console Application template, and give it a name (I chose FileSystemSyncher.Console
to keep in sync with the solution).
Figure 1.2
After we click OK, the project will show up in our Solution Explorer like in figure 1.3.
Figure 1.3
First, we would like the source path and the destination path to be configurable, so for this, we will need to add a reference to “System.Configuration
”, to do this, we will need to right click either on the project FileSystemSyncher.Console
or right clicking the references node inside the project and then clicking Add Reference… afterwards, we go to the assemblies tab and add the “System.Configuration
” reference.
If we want to leverage the “ConfigurationManager
”, we will also need to add to the Programfile, the using System.Configuration
namespace.
So, after all that, we would have to add in the App.configfile the following section and lines so we can configure our paths in the future (see figure 1.4).
Figure 1.4
Here, I added two keys, one for the paths and set them to two folders I had set up to test the application, you can use whatever path you wish.
Next, we implement the code to get the paths and validate them (figure 1.5).
Figure 1.5
So what we did here is as follows:
- We added a
global try
…catch
block so in case something goes wrong, or a validation fails, then the application outputs the problem and doesn’t just dump the error in the Window’s Event Log. - We retrieved the source path from the config file, because the source path is mandatory for our application to run, we check if the path is empty or
null
(in which case the path was not set in the configuration file). - If the configuration was set, we then use the “
Path.GetFullPath
” (from the “System.IO
” namespace) method to get the whole path of the source folder, this will ensure that we find the path even if it’s relative to the application’s location. - Then we check if that path is really valid and that the directory for that path really exists on the drive, if not we throw an exception telling the user that the source path does not exist.
- After that part, we do the same for the destination, also checking that it has been filled out.
- If the destination was filled out, we use the “
Path.GetFullPath
” (from the “System.IO
” namespace) method again so we can use absolute and relative paths to the application’s location. - Seeing how the destination path is not mandatory to exist, we check if it already exists, if it doesn’t then we create it with the path that was provided.
With these bits of code, we made sure that both the paths have been filled out and that they are both valid and exist.
Next, we will see the actual implementation of the sync part of the application (figure 1.6):
Figure 1.6
After we checked the paths, we do the following:
- Create a
DirectoryInfo
of the source path, this will let us enumerate files as object and not just as paths. - Next, we use the “
EnumerateFiles
” method with a filter of “*
” meaning we get all the files, and the “SearchOption.AllDirectories
” flag so we can enumerate through every file under the source directory no matter how deeply nested it is. - We take the full path of the file found in the source folder, and we replace the source path with the destination path.
- Afterwards, we create a new “
FileInfo
” for the destination path so we can compare the two of them. - We then check if the files already exists in the destination folder, and if it does, we check that it has the same size and write time as the one in the source folder (this is a very crude check but it will work for most cases).
- If the destination file does not exist or it is changed, we will first try and create the folder path to it (fun fact about “
CreateDirectory
” is that if the folder already exists, then it does nothing) because if the folder does not exist, then we will get an exception, then we copy the source file over the destination file specifying that we should overwrite it.
We just created our first feature of getting files from point A from a given path to point B even if point B doesn’t exist.
There are a few warnings to this implementation at the moment and those are:
- This will only copy files and the folder they reside in, it will not copy empty folders.
- Both paths need to have access permissions and the destination path should also have write permissions for the current user that is running the console.
The source code for the end of this step can be found here.
I also added the compiled executable with the configuration file if you want to play with it.
Coming Up Next
We saw how to make a simple tool to copy files, next up, we will clean up the code so we can make some room for further enhancements and future features.
Join me next time as we journey though the makings of a tool step by step.
Thank you for reading.
CodeProject