C#下的WPF应用程序:文件比对兼副本创建工具

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

时间: 2024-10-03 23:16:45

C#下的WPF应用程序:文件比对兼副本创建工具的相关文章

WPF应用程序防止关闭LiteDB数据库文件加载事件

在WPF应用程序的主窗口和它的Window.Loaded事件我得到一些数据从LiteDB数据库文件. var groupViewModel = new GroupsViewModel();ComboBoxGroupsName.ItemsSource = groupViewModel.GetGroups();的GetGroups方法是这样的: IEnumerable<GroupModel> groups;using (var db = new LiteDatabase(DbFilePath)){

在VS2008.Net下使用WPF开发Web应用程序

原文地址:http://hankjin.blog.163.com/blog/static/33731937200922353623434/ 胖客户端的好处是可以轻易的实现绚丽的效果, 而瘦客户端则需要大量的js才能实现相应的效果. 而且当需要同时开发应用程序和Web应用程序时, 则需要将近双倍的开发时间.但是,在VS2008.Net下使用WPF技术, 则不但可以轻松地在Web上实现应用程序的效果, 而且可以很简单的将应用程序转换成Web应用程序.1. 新建->项目->WPF Web Appli

linux文件夹下递归执行脚本/程序

在linux中,若需要使用某个脚本/程序对文件夹下所有符合条件的文件执行,可采用如下方法: 首先是find命令,用find找出符合条件的待执行文件/文件夹 ## 只列出常规文件 find ./ -type f ## 只列出文件夹 find ./ -type d ## 列出后缀cpp的文件 find -name *.cpp 对找到的所有文件批处理 find ./ -type f -exec chmod 644 {} \; # 后面的\;必须的,表示按行输出 find ./ -type d -exe

编写一个程序,将 d: \ java 目录下的所有.java 文件复制到d: \ jad 目录下,并 将原来文件的扩展名从.java 改为.jad

1.编写一个程序,将 d: \ java 目录下的所有.java 文件复制到d: \ jad 目录下,并 将原来文件的扩展名从.java 改为.jad package copy; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; i

Ubuntu16.04下写的Qt程序,调试时没问题,运行时偶现崩溃 (需要在运行时生成core dump文件,QMAKE_CC += -g)

记录一下 Ubuntu16.04下写的Qt程序,调试时没问题,运行时偶现崩溃 需要在运行时生成core dump文件 首先在pro结尾里加入 QMAKE_CC += -g QMAKE_CXX += -g QMAKE_LINK += -g 在终端输入 ulimit -c 显示为 0 然后输入 ulimit -c unlimited 继续在终端运行编写的程序 出错后,会在当前目录生成 core 文件 然后在终端执行 “gdb 你的程序名 core” 然后输入 bt 对该错误进行跟踪调试 (gdb)

C#/WPF让程序开机自动启动

最近一个C/S项目客户要求开机自启的功能,网上找了一些方法,不顶用:最后自己去翻书,找到了这段代码,亲测可用,Wpf环境下需要改下获取程序目录的方式即可,Winform直接可用. 1 #region 设置开机自启 2 string strName = AppDomain.CurrentDomain.BaseDirectory + "AutoRunPro.exe";//获取要自动运行的应用程序名 3 if (!System.IO.File.Exists(strName))//判断要自动运

WPF 中style文件的引用

原文:WPF 中style文件的引用 总结一下WPF中Style样式的引用方法: 一,内联样式: 直接设置控件的Height.Width.Foreground.HorizontalAlignment.VerticalAlignment等属性.以设置一个Botton控件的样式为例,如: 复制代码 <Grid x:Name="ContentPanel" > <Button Content="Button" Name="btnDemo"

在VS下运转C言语程序

即便读者决议运用VS,不运用C-Free或VC6.0,我依然建议浏览<在C-Free下运转C言语程序><在VC6.0下运转C言语程序>,文中讲到几个主要概念,对初学者大有裨益. 微软后来对VC6.0停止了晋级,并改名为Visual Studio(简称VS),支撑更多的编程言语,愈加弱小的功用,不外 Visual Studio 文件很大,有2~3G阁下,大局部功用初学者临时不会用到:并且装置繁琐,需求快要半个小时的工夫,也不轻易卸载洁净.Visual Studio 还有一个缺陷是占用

windows下调用外部exe程序 SHELLEXECUTEINFO

本文主要介绍两种在windows下调用外部exe程序的方法: 1.使用SHELLEXECUTEINFO 和 ShellExecuteEx SHELLEXECUTEINFO 结构体的定义如下: 1 typedef struct _SHELLEXECUTEINFO { 2 DWORD cbSize; 3 ULONG fMask; 4 HWND hwnd; 5 LPCTSTR lpVerb; 6 LPCTSTR lpFile; 7 LPCTSTR lpParameters; 8 LPCTSTR lpD