1.关于本工具
这个工具是我用WPF写的一个测试工具,需求大致上是:有一个文件,它不定期会发生变化,现在要求监控这个文件,每当该文件改变,则创建一个该文件的副本。
在这个程序中,指定一个被监控文件的路径,设定一个拍摄快照的时间间隔,每次拍摄文件的快照后,根据设定比对当次快照与之前快照中文件的大小或最后修改时间,发生变化则创建副本。副本的文件名是当前的时间(时、分、秒、毫秒),副本的扩展名与被监控的文件一致。
程序启动时可以从config.xml中读取配置:
<?xml version="1.0" encoding="gb2312"?>
<Config>
<FilePath>test.txt</FilePath>
<MonInterval>200</MonInterval>
<MonType>1</MonType>
</Config>
程序的副本被复制到一个名为copy的文件夹中
config.xml与文件夹copy都在工程目录中,在编译后通过后期生成事件命令行复制到可执行文件所在目录下
xcopy "$(ProjectDir)config\config.xml" "$(TargetDir)" /Y
xcopy "$(ProjectDir)copy\test.txt" "$(TargetDir)"\copy\ /Y
2.程序界面
界面布局的xaml文档为:
<Window x:Name="wndwCyclop" x:Class="Cyclop.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Cyclop" Height="329" Width="472" ResizeMode="CanMinimize"
WindowStartupLocation="CenterScreen" Loaded="wndwCyclop_Loaded"
Icon="Cyclop.ico">
<Grid Margin="0,0,4,-2">
<!--程序标题-->
<Label x:Name="lblTitle" Content="Cyclop 文件比对兼副本创建工具"
HorizontalAlignment="Left" Margin="42,21,0,0"
VerticalAlignment="Top" FontSize="24"
FontFamily="YouYuan" FontWeight="Bold"/>
<!--被监控文件路径-->
<Label x:Name="lblFilePath" Content="被监控文件路径:"
HorizontalAlignment="Left" Margin="31,76,0,0"
VerticalAlignment="Top" Width="101"/>
<TextBox x:Name="txtFilePath" HorizontalAlignment="Left"
Height="23" Margin="146,79,0,0" Text=""
VerticalAlignment="Top" Width="194"/>
<Button x:Name="btnBrowse" Content="..."
HorizontalAlignment="Left" Margin="354,80,0,0"
VerticalAlignment="Top" Width="75"
RenderTransformOrigin="0.747,0.364" Click="btnBrowse_Click"/>
<!--快照时间间隔(单位毫秒)-->
<Label x:Name="lblInterval" Content="快照时间间隔ms:"
HorizontalAlignment="Left" Margin="31,107,0,0"
VerticalAlignment="Top" Width="101"/>
<TextBox x:Name="txtInterval" HorizontalAlignment="Left"
Height="23" Margin="146,110,0,0" Text=""
VerticalAlignment="Top" Width="194"/>
<!--监控选项-->
<RadioButton x:Name="rdbSizeOnly" Content="监控文件大小"
HorizontalAlignment="Left" Margin="102,158,0,0"
VerticalAlignment="Top"
ToolTip="仅监控文件的大小,该项属性改变时创建副本"/>
<RadioButton x:Name="rdbTimeOnly" Content="监控最后修改时间"
HorizontalAlignment="Left" Margin="249,158,0,0"
VerticalAlignment="Top"
ToolTip="仅监控文件的最后修改时间,该项属性改变时创建副本"/>
<Button x:Name="btnStart" Content="开始监控" HorizontalAlignment="Left"
Margin="60,209,0,0" VerticalAlignment="Top" Width="153" Height="48"
RenderTransformOrigin="0.5,0.5" Click="btnStart_Click">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleX="27.474"/>
<RotateTransform/>
<TranslateTransform X="-12.48"/>
</TransformGroup>
</Button.RenderTransform>
</Button>
<Button x:Name="btnStop" Content="中止监控" HorizontalAlignment="Left"
Margin="243,209,0,0" VerticalAlignment="Top" Width="153" Height="48"
RenderTransformOrigin="0.5,0.5" IsEnabled="False" Click="btnStop_Click">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleX="-27.474"/>
<RotateTransform/>
<TranslateTransform X="12.48"/>
</TransformGroup>
</Button.RenderTransform>
</Button>
</Grid>
</Window>
3.程序源码
/*
* Cyclop 文件比对兼副本创建工具
* 作者姓名:Tsybius
* 创建时间:2014-12-02
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
// 代码中需要手动添加的命名空间
using System.IO;
using System.Xml;
using System.Windows.Threading; // DispatcherTimer要用到它
using Microsoft.Win32; // OpenFileDialog要用到它
namespace Cyclop
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// 被监控文件的大小
/// </summary>
long lFileSize = -1;
/// <summary>
/// 被监控文件的最后修改日期
/// </summary>
DateTime dtLastWrite = new DateTime(2000, 1, 1, 0, 0, 0);
/// <summary>
/// 监控文件大小和信息
/// </summary>
DispatcherTimer dsptMon = new DispatcherTimer();
/// <summary>
/// 加载界面时触发:读取配置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void wndwCyclop_Loaded(object sender, RoutedEventArgs e)
{
try
{
// 初始化控件值
this.txtFilePath.Text = "";
this.txtInterval.Text = "1000";
this.rdbSizeOnly.IsChecked = true;
if (!File.Exists("config.xml"))
{
throw new Exception("没有找到配置文件,程序将启动默认配置");
}
// 读取配置文件
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("config.xml");
XmlNode nodeRoot = xmlDoc.SelectSingleNode("Config");
XmlNodeList nodeList = nodeRoot.ChildNodes;
foreach (XmlNode node in nodeList)
{
switch (((XmlElement)node).Name)
{
case "FilePath":
{
this.txtFilePath.Text = ((XmlElement)node).InnerText;
}
break;
case "MonInterval":
{
this.txtInterval.Text = ((XmlElement)node).InnerText;
}
break;
case "MonType":
{
switch (((XmlElement)node).InnerText)
{
case "1":
{
this.rdbSizeOnly.IsChecked = true;
}
break;
case "2":
{
this.rdbTimeOnly.IsChecked = true;
}
break;
default:
break;
}
}
break;
default:
break;
}
}
// 设置定时器内容
dsptMon = new DispatcherTimer();
dsptMon.Interval = new TimeSpan(1000);
dsptMon.Tick += (arg, obj) =>
{
FileInfo fi = new FileInfo(txtFilePath.Text);
long size = fi.Length;
DateTime last = fi.LastWriteTime;
//监控文件大小的改变,改变则创建文件副本
if ((bool)rdbSizeOnly.IsChecked)
{
if (fi.Length != lFileSize)
{
File.Copy(txtFilePath.Text,
"copy/" + DateTime.Now.ToString("HHmmss_fff") +
fi.Extension.ToLower());
lFileSize = fi.Length;
return;
}
}
//监控文件最后修改时间的改变,改变则创建文件副本
else if ((bool)rdbTimeOnly.IsChecked)
{
if (fi.LastWriteTime.Year != dtLastWrite.Year ||
fi.LastWriteTime.Month != dtLastWrite.Month ||
fi.LastWriteTime.Day != dtLastWrite.Day ||
fi.LastWriteTime.Hour != dtLastWrite.Hour ||
fi.LastWriteTime.Minute != dtLastWrite.Minute ||
fi.LastWriteTime.Second != dtLastWrite.Second ||
fi.LastWriteTime.Millisecond != dtLastWrite.Millisecond)
{
File.Copy(txtFilePath.Text,
"copy/" + DateTime.Now.ToString("HHmmss_fff") +
fi.Extension.ToLower());
dtLastWrite = fi.LastWriteTime;
return;
}
}
};
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// 选择被监控的文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnBrowse_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.CheckFileExists = true;
openFileDialog.CheckPathExists = true;
openFileDialog.ReadOnlyChecked = false;
openFileDialog.Multiselect = false;
openFileDialog.Filter = "所有文件|*.*";
openFileDialog.Title = "选择文件";
if ((bool)openFileDialog.ShowDialog())
{
this.txtFilePath.Text = openFileDialog.FileName;
}
}
/// <summary>
/// 按钮:开始监控
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click(object sender, RoutedEventArgs e)
{
// 检查输入是否合法
if (!File.Exists(this.txtFilePath.Text))
{
MessageBox.Show("被监控文件路径非法");
return;
}
bool b;
int interval;
b = int.TryParse(this.txtInterval.Text, out interval);
if (!b || interval < 100)
{
MessageBox.Show("快照时间间隔必须是不小于100的整数");
return;
}
//锁定所有设置项
this.txtFilePath.IsEnabled = false;
this.txtInterval.IsEnabled = false;
this.rdbSizeOnly.IsEnabled = false;
this.rdbTimeOnly.IsEnabled = false;
this.btnStart.IsEnabled = false;
this.btnStop.IsEnabled = true;
// 获取文件信息和计时器时间间隔
lFileSize = -1;
dtLastWrite = new DateTime(2000, 1, 1, 0, 0, 0);
dsptMon.Interval = new TimeSpan(interval);
// 打开计时器
dsptMon.Start();
}
/// <summary>
/// 按钮:中止监控
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStop_Click(object sender, RoutedEventArgs e)
{
// 关闭计时器
dsptMon.Stop();
//解锁所有设置项
this.txtFilePath.IsEnabled = true;
this.txtInterval.IsEnabled = true;
this.rdbSizeOnly.IsEnabled = true;
this.rdbTimeOnly.IsEnabled = true;
this.btnStart.IsEnabled = true;
this.btnStop.IsEnabled = false;
}
}
}
END