最近客户提出他们需要一个每日定时自动备份的工具,总共有三台服务器,一台是文件服务器,一台是数据库服务器,然后他们希望每天可以定时从这两台服务器上把文件跟数据库备份到第三台备份服务器上。通过对这个工具的开发,让我对windows服务有了一个初步的了解,通过文件共享和批处理命令的方法备份文件和数据库。希望可以跟各位园友分享一下。
这个小工具项目主要分为三层:
第一层提供一个winform界面层,可以让用户自己输入开启服务的配置信息,具体界面如下:
在winform界面上输入完这些配置信息后,点击完成备份配置按钮,就会映射界面上的数据,保存到第二层配置层里的配置文件中,这里运用了xml序列化和反序列化,单例模式,代码如下:
1 public class ConfigLoader 2 { 3 public static readonly ConfigLoader Instance = new ConfigLoader(); 4 5 private ParameterConfig _config = null; 6 public ParameterConfig ParameterConfig 7 { 8 get 9 { 10 if (_config == null) 11 { 12 _config = new ParameterConfig(); 13 } 14 return _config; 15 } 16 } 17 private ConfigLoader() 18 { 19 string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ParameterConfig.xml"); 20 _config = SerializableHelper.DeSerializableXML<ParameterConfig>(path); 21 } 22 /// <summary> 23 /// 保存服务配置参数 24 /// </summary> 25 public void SaveParameterConfig(ParameterConfig config) 26 { 27 string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ParameterConfig.xml"); 28 SerializableHelper.SerializableXML<ParameterConfig>(config, path); 29 } 30 /// <summary> 31 /// 重置配置参数 32 /// </summary> 33 public void Reset() 34 { 35 _config = null; 36 } 37 }
最后的主要功能实现就在服务层了,里面有一个服务功能类和服务安装信息类,在服务功能类中添加了一个定时器Timer,通过这个小家伙来让它每天准时来为我们打工~备份文件的方法是用递归与多线程,代码具体如下:
public class CopyDirectoryHelper { /// <summary> /// 源目录 /// </summary> private DirectoryInfo _Source; /// <summary> /// 目标目录 /// </summary> private DirectoryInfo _Target; /// <summary> /// 文件复制完成 /// </summary> /// <param name="FileCount">文件数量合计</param> /// <param name="CopyCount">复制完成的数量</param> /// <param name="FileSize">文件大小合计</param> /// <param name="CopySize">复制完成的大小</param> /// <param name="FileName">复制完成的文件名</param> public delegate void CopyRun(int FileCount,int CopyCount,long FileSize,long CopySize,string FileName); public event CopyRun MyCopyRun; /// <summary> /// 复制完成 /// </summary> public delegate void CopyEnd(); public event CopyEnd MyCopyEnd; private int _FileCount = 0; private int _CopyCount = 0; private long _FileSize = 0; private long _CopySize = 0; /// <summary> /// 复制目录包含文件 /// </summary> /// <param name="p_SourceDirectory">源目录</param> /// <param name="p_TargetDirectory">目标目录</param> public CopyDirectoryHelper(string p_SourceDirectory, string p_TargetDirectory) { _Source = new DirectoryInfo(p_SourceDirectory); _Target = new DirectoryInfo(p_TargetDirectory); FileSystemInfo[] Temp = _Source.GetFileSystemInfos(); } /// <summary> /// 开始复制 /// </summary> public void StarCopy() { GetFile(_Source); Thread Th = new Thread(new ThreadStart(Run)); Th.Start(); } private void Run() { Copy(_Source,_Target ); if (MyCopyEnd != null) MyCopyEnd(); } /// <summary> /// 复制目录到指定目录 /// </summary> /// <param name="source">源目录</param> /// <param name="target">目标目录</param> private void GetFile(DirectoryInfo MySiurceDirectory) { foreach (FileInfo _File in MySiurceDirectory.GetFiles()) //循环文件 { _FileCount++; _FileSize += _File.Length; } foreach (DirectoryInfo _SourceSubDir in MySiurceDirectory.GetDirectories()) //循环子目录 { GetFile(_SourceSubDir); } } /// <summary> /// 复制目录到指定目录 /// </summary> /// <param name="source">源目录</param> /// <param name="target">目标目录</param> private void Copy(DirectoryInfo p_Source, DirectoryInfo p_Target) { if (!Directory.Exists(p_Target.FullName))Directory.CreateDirectory(p_Target.FullName); foreach (FileInfo _File in p_Source.GetFiles()) //循环文件 { if (!File.Exists(Path.Combine(p_Target.ToString(), _File.Name))) { _File.CopyTo(Path.Combine(p_Target.ToString(), _File.Name), true); _CopyCount++; _CopySize += _File.Length; if (MyCopyRun != null) MyCopyRun(_FileCount, _CopyCount, _FileSize, _CopySize, _File.Name); } } foreach (DirectoryInfo _SourceSubDir in p_Source.GetDirectories()) //循环子目录 { DirectoryInfo _NextDir = p_Target.CreateSubdirectory(_SourceSubDir.Name); Copy(_SourceSubDir, _NextDir); } } }
备份数据库的工具就让oracle来帮我们做吧,开启一个进程来执行我们写好的可以传进参数的批处理命令,具体代码如下:
public class ExcuteProcess { public static void ExecuteCommand(string fileName, string command, string dbName, string dbPwd, string serverName, string backupPath) { Process p = new Process(); //string path = "backupDb.bat";//bat路径 ProcessStartInfo pi = new ProcessStartInfo(fileName, dbName + " " + dbPwd + " " + serverName + " " + backupPath);//第二个参数为传入的参数,string类型以空格分隔各个参数 pi.CreateNoWindow = true; pi.UseShellExecute = false; pi.RedirectStandardOutput = true; p.StartInfo = pi; p.Start(); p.WaitForExit(); string output = p.StandardOutput.ReadToEnd(); } }
最后只要手动安装一下这个服务程序,在cmd窗口输入命令:InstallUnit BackupFileService.exe。就大工告成啦!有兴趣的朋友可以下载一下源码,有什么意见和心得,小弟随时欢迎各位园友的交流!