Let's Synchronize Some Files
Recently, I posted about the new addition to my backup strategy; a NAS. My intended use of this device is to have a hot backup of my files. The system I was using before was not capable of storing the amount of data I need backed up, nor was it easy to manage.
I modified the set of xCopy batch files that I used for my backups to write the files to the NAS.
This system worked fine, but I needed more. I manage a lot of data and have a lot of files. I wouldn't want to lose any in the event of a system failure. The one problem I see with using this process is the lack of a real time solution.
I was in search of a solution that would offer me real-time synchronization between my files and the NAS. I didn't have to search very far. The .NET Framework includes the FileSystemWatcher Class.
The FileSystemWatcher Class "Listens to the file system change notifications and raises events when a directory, or file in a directory, changes." (quoted directly from MSDN) After reading through this class I quickly whipped up a solution. I developed my own FileSync class that allowed me to easily synchronize files between my remote and local storage. I created a Windows Service (threaded) built around my class (the screen shot in this post is from a sample app I used to test my class) so that I could have the FileSync class running and keeping my files in sync without me needing to do anything. Here is the unit I created:
1
using System;
2
using System.IO;
3
using System.Diagnostics;
4
5
namespace BPSoftware
6
...{
7
class FileSync
8
...{
9
private FileSystemWatcher watcher;
10
11
Fields#region Fields
12
private string destpath;
13
public string DestPath
14
...{
15
get ...{ return destpath; }
16
set ...{ destpath = value; }
17
}
18
19
private string sourcepath;
20
public string SourcePath
21
...{
22
get ...{ return sourcepath; }
23
set ...{ sourcepath = value; }
24
}
25
26
private string filter;
27
public string Filter
28
...{
29
get ...{ return filter; }
30
set ...{ filter = value; }
31
}
32
33
private bool watchsubfolders;
34
public bool WatchSubFolders
35
...{
36
get ...{ return watchsubfolders; }
37
set ...{ watchsubfolders = value; }
38
}
39
#endregion
40
41
Constructors#region Constructors
42
public FileSync()
43
...{
44
this.watcher = new FileSystemWatcher();
45
this.watcher.InternalBufferSize = 0x20000;
46
this.watcher.NotifyFilter = NotifyFilters.FileNameNotifyFilters.LastWrite;
47
this.watcher.IncludeSubdirectories = false;
48
this.watcher.Changed += new FileSystemEventHandler(this.OnChanged);
49
this.watcher.Created += new FileSystemEventHandler(this.OnCreated);
50
this.watcher.Deleted += new FileSystemEventHandler(this.OnDeleted);
51
this.watcher.Renamed += new RenamedEventHandler(this.OnRenamed);
52
}
53
54
public FileSync(string source, string destination, string filefilter, bool watchsubs): this()
55
...{
56
this.SourcePath = source;
57
this.DestPath = destination;
58
this.Filter = filefilter;
59
this.WatchSubFolders = watchsubs;
60
}
61
#endregion
62
63
Methods#region Methods
64
private string GetDestinationFile(string infile)
65
...{
66
string fileName = Path.GetFileName(infile);
67
return (this.destpath + fileName);
68
}
69
70
private void LogEvent(string message, int id)
71
...{
72
EventLog.WriteEntry("FileSync", message, EventLogEntryType.Error, id);
73
}
74
75
public void Start()
76
...{
77
try
78
...{
79
if (this.watcher != null)
80
...{
81
this.watcher.Path = this.SourcePath;
82
this.watcher.Filter = this.Filter;
83
this.watcher.IncludeSubdirectories = this.WatchSubFolders;
84
this.watcher.Filter = this.Filter;
85
this.watcher.EnableRaisingEvents = true;
86
}
87
}
88
catch (Exception exception)
89
...{
90
this.LogEvent(exception.Message, 0x01);
91
}
92
}
93
94
public bool Stop()
95
...{
96
try
97
...{
98
if (this.watcher != null)
99
...{
100
this.watcher.EnableRaisingEvents = false;
101
this.watcher.Changed -= new FileSystemEventHandler(this.OnChanged);
102
this.watcher.Created -= new FileSystemEventHandler(this.OnCreated);
103
this.watcher.Deleted -= new FileSystemEventHandler(this.OnDeleted);
104
this.watcher.Renamed -= new RenamedEventHandler(this.OnRenamed);
105
}
106
}
107
catch (Exception exception)
108
...{
109
this.LogEvent(exception.Message, 0x02);
110
return false;
111
}
112
return true;
113
}
114
#endregion
115
116
Events#region Events
117
private void OnChanged(object source, FileSystemEventArgs e)
118
...{
119
try
120
...{
121
File.Copy(e.FullPath, this.GetDestinationFile(e.FullPath), true);
122
}
123
catch (Exception exception)
124
...{
125
this.LogEvent(exception.Message, 0x03);
126
}
127
}
128
129
private void OnCreated(object source, FileSystemEventArgs e)
130
...{
131
try
132
...{
133
File.Copy(e.FullPath, this.GetDestinationFile(e.FullPath));
134
}
135
catch (Exception exception)
136
...{
137
this.LogEvent(exception.Message, 0x04);
138
}
139
}
140
141
private void OnDeleted(object source, FileSystemEventArgs e)
142
...{
143
try
144
...{
145
File.Delete(this.GetDestinationFile(e.FullPath));
146
}
147
catch (Exception exception)
148
...{
149
this.LogEvent(exception.Message, 0x05);
150
}
151
}
152
153
private void OnRenamed(object source, RenamedEventArgs e)
154
...{
155
try
156
...{
157
File.Move(this.GetDestinationFile(e.OldFullPath), this.GetDestinationFile(e.FullPath));
158
}
159
catch (Exception exception)
160
...{
161
this.LogEvent(exception.Message, 0x06);
162
}
163
}
164
#endregion
165
}
166
}
167